LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Newbie (http://www.linuxquestions.org/questions/linux-newbie-8/)
-   -   Sed wraps some lines, not all (http://www.linuxquestions.org/questions/linux-newbie-8/sed-wraps-some-lines-not-all-869049/)

kristo5747 03-16-2011 06:25 PM

Sed wraps some lines, not all
 
Greetings. I am using SED to cleanup files that are laid out like so:

Code:

 
ReceiverID=028936004663
SerialNumber=WD-WCAV95708405
Currenttemp=44C
PowerOnHours=3663h
ReceiverID=028923894902
SerialNumber=WD-WCAV9A766701
Currenttemp=49C
PowerOnHours=2215h

My boss wants files like this one to be tab ("\t") delimited like so

Code:

ReceiverID=...(tab)SerialNumber=...(tab)Currenttemp=...(tab)PowerOnHours=...(newline)
ReceiverID=...(tab)SerialNumber=...(tab)Currenttemp=...(tab)PowerOnHours=...(newline)...

1) first, I added a newline to mark each record
Code:

sed -i 's/h/h\n/g' infile
,
2) then, I added the the tab delimiter
Code:

    sed -i '/.$/N; s/.\n/\t/' infile
It works but strangely, not everywhere. This is the output I get

Code:

ReceiverID=...(tab)SerialNumber=...(tab???)
Currenttemp=...(tab)PowerOnHours=...(newline)
ReceiverID=...(tab)SerialNumber=...(tab???)
Currenttemp=...(tab)PowerOnHours=...(newline)

What am I missing?? I welcome your input. Thanks.

grail 03-17-2011 12:52 AM

So I understand why your output is not working, but my sed-jitsu is not good enough to correct it (I am sure one of the gurus will help).

I can tell you that:

1. Your first step adds no real benefit, at least not for what happens in the second.

2. Once 'N' is called the next time through it effectively looks at the alternating odd lines.
So first time through it grabs line 2 and appends to line 1 and replaces last character plus '\n' with '\t'
On the next iteration it looks at line 3 and then calls 'N' which grabs line 4 (this is unlike your expectation that it would look at line 2 and grab line 3)

I believe you need to use the ':' and 't' looping ability, but sadly I could not find the right combinations.

However, as an alternate, here is an awk solution:
Code:

awk 'NR>1 && /Receiver/{$0="\n"$0}1' ORS="\t" file

kristo5747 03-17-2011 11:50 AM

Quote:

Originally Posted by grail (Post 4293428)
So I understand why your output is not working, but my sed-jitsu is not good enough to correct it (I am sure one of the gurus will help).

I can tell you that:

1. Your first step adds no real benefit, at least not for what happens in the second.

2. Once 'N' is called the next time through it effectively looks at the alternating odd lines.
So first time through it grabs line 2 and appends to line 1 and replaces last character plus '\n' with '\t'
On the next iteration it looks at line 3 and then calls 'N' which grabs line 4 (this is unlike your expectation that it would look at line 2 and grab line 3)

I believe you need to use the ':' and 't' looping ability, but sadly I could not find the right combinations.

However, as an alternate, here is an awk solution:
Code:

awk 'NR>1 && /Receiver/{$0="\n"$0}1' ORS="\t" file

After *lots* of trials/errors, I got this (with help from people smarter than me):

Code:

#! /bin/bash
while read line; do
    [[ "$line" =~ PowerOnHours ]] && {
        printf '%s\n' "$line"
    } || {
        printf '%s\t' "$line"
    }
done <myfile

I don't even need to add the newline after PowerOnHours (no added value, really). It gets me the output I was looking for

Code:

Receiver ID  = 028918576472    Serial Number = WD-WCAUK0635287 Current temp  = 50C    PowerOnHours  = 12972h
Receiver ID  = 028968505835    Serial Number = WD-WCAUH1726359 Current temp  = 48C    PowerOnHours  = 9591h

Thanks for your time.:D

crts 03-17-2011 06:59 PM

Hi,

I know this is solved but since you initially asked for a sed solution I thought I'll provide one:
Code:

sed -n '/ReceiverID/ {h;b};H;/PowerOnHours/ {x;s/\n/\t/g;p}' file


All times are GMT -5. The time now is 01:27 AM.