Smart questions
Smart answers
Smart people
INTELLIGENT WORK FORUMS
FOR COMPUTER PROFESSIONALS

Member Login




Remember Me
Forgot Password?
Join Us!

Come Join Us!

Are you a
Computer / IT professional?
Join Tek-Tips now!
  • Talk With Other Members
  • Be Notified Of Responses
    To Your Posts
  • Keyword Search
  • One-Click Access To Your
    Favorite Forums
  • Automated Signatures
    On Your Posts
  • Best Of All, It's Free!

Join Tek-Tips
*Tek-Tips's functionality depends on members receiving e-mail. By joining you are opting in to receive e-mail.

Donate Today!

Do you enjoy these
technical forums?
Donate Today! Click Here

Posting Guidelines

Promoting, selling, recruiting, coursework and thesis posting is forbidden.
Jobs from Indeed

Link To This Forum!

Partner Button
Add Stickiness To Your Site By Linking To This Professionally Managed Technical Forum.
Just copy and paste the
code below into your site.

sed if/else or branching?Helpful Member! 

blarneyme (MIS)
27 Mar 12 9:38
This question came up in another thread so I wanted to see if
it could be done purely with [b]sed[\b] instead of awk or shell.

Quote:


# cat text
A 0
A 1
B 2
C 3
C 4
C 5
D 6
D 7
E 8
E 9
The output should be

Quote:


A 0,1
B 2
C 3,4,5
D 6,7
E 8,9
I've come close but am missing how to evaluate the first column of the next line with the previous

CODE

sed '/^$/!{
h
s/\(.*\) \(.*\)\n/\1/
N
s/\(.*\) \(.*\)\n/\1 \2,/
s/,[A-Z]/,/
s/, /,/
}' text

This is my output as it stands now

Quote:


# ./s
A 0,1
B 2,3
C 4,5
D 6,7
E 8,9

Any ideas how to branch or do an if/else test to get it to print as expected?
blarneyme (MIS)
27 Mar 12 14:59
I am closer, but still have a problem when column 1 has more than 2 variables.

CODE

# cat ss
sed '/^$/!{
h
bb
s/\(.*\) \(.*\)\n/\1 \2,/;
s/,[A-Z]/,/;
s/, /,/;
:b
/^A/{
 s/\(.*\) \(.*\)\n/\1/;
 N
 s/\(.*\) \(.*\)\n/\1 \2,/;
 s/,[A-Z]/,/;
 s/, /,/;
}
/^B/{
 s/\(.*\) \(.*\)\n/\1/p;
 N
 /^\(.*\)\n\1$/ {
    bb
 }
}
/^C/{
 s/\(.*\) \(.*\)\n/\1/;
 N
 s/\(.*\) \(.*\)\n/\1 \2,/;
 s/,[A-Z]/,/;
 s/, /,/;
 /^\(.*\)\n\1$/ {
   bb
 }
}
/^D/{
 s/\(.*\) \(.*\)\n/\1/;
 N
 s/\(.*\) \(.*\)\n/\1 \2,/;
 s/,[A-Z]/,/;
 s/, /,/;
}
/^E/{
 s/\(.*\) \(.*\)\n/\1/;
 N
 s/\(.*\) \(.*\)\n/\1 \2,/;
 s/,[A-Z]/,/;
 s/, /,/;
}
}' text

Quote:


# cat text
A 0
A 1
B 2
C 3
C 4
C 5
D 6
D 7
E 8
E 9
output

Quote:


# ./ss
A 0,1
B 2
C 3
C 4,5
D 6,7
E 8,9
FlorianAwk (Programmer)
28 Mar 12 2:48
Hello,

Here is my console:

bash$ cat test.txt
A 0
A 1
B 2
C 3
C 4
C 5
D 6
D 7
E 8
E 9
bash$ sed '1h;1!H;g;s/\(.*\)\([A-Z]\) \(.*\)\n\2 \(.*\)/\1\2 \3,\4/;h;$!d' test.txt
A 0,1
B 2
C 3,4,5
D 6,7
E 8,9


Do you need more explanations ? :)
Using \( and \) allows sed to identify a group of characters and reuse them by \1 \2 \3 respecting the order.
blarneyme (MIS)
28 Mar 12 7:44
If you have time, could you break down the one-liner by each command and how it works with the input.

Something like:
1h  copies line A0 from pattern space to holding space
1H  appends line A1 from the pattern space to the holding space
g   copies line A 0 A 1 from holding space to pattern space replacing the current line
s/  what is the \n\2 ?

Also my A 0 A 1 must not be correct because your substitution has (.*)([A-Z])(.*)(.*) and I would have expected a ([A-Z])(.*)([A-Z])(.*)  and I understand the newline, just would have expected it after the second pair of ()() not the third and still not understanding the \2 after the newline.

If you have time I'd appreciate your explanations!  
Thanks!
Helpful Member!  FlorianAwk (Programmer)
28 Mar 12 18:44
Ok. The idea is to append the next line, for each cycle, into the holding space, deleting the already existing capital and adding commas

1h; When? For the first line. What? Put working space into holding space
1!H; When? Always except the first line. What? Append working space into holding space. Why? To concatenate the new line to what we have already done.
g; When? Always. What? Put holding space into working space. Why? To work on it.
s/\(.*\)\([A-Z]\) \(.*\)\n\2 \(.*\)/\1\2 \3,\4/; substitution processing
h; When? Always. What? Put working space into holding space. Why? To prepare the next cycle.
$!d; When? Always except the last line. What? Clear working space. Why? Not to see result on screen. Remove it to see the evolution on screen.


Let's examinate the substitution:

When?
s/blabla/bloblo/ the first time
s/blabla/bloblo/2 the two first time
s/blabla/bloblo/g always

. -> any character
.* -> 0 or more character(s)
.+ -> 1 or more character(s)
.? -> 0 or 1 character (not sure. Maybe .\? )
\n -> end of line. Putting a new line (by N, G or H) is the way to concatenate multilines. You can choose to substitute \n or not.
^ -> beginning of line
$ -> end of line in regular expressions (but last line in the sed adressing system. Don't be confused)

What is the first block? Anything. Surely, what we have already done.
What is the second block? A capital.
What is the third block? Anything. Surely the numbers, separated by commas
What is the fourth block? Anything. Surely the last new number
What is the first \2? The same capital. Why not [A-Z]? Because any pair of capitals matches. Not only a capital twice.

The subtitution seems to delete the \n. Why can we see few lines? Because when you change the capital, the pattern is not recognized and the substitution is not done.
If I write 's/\n/ /g', would it write everything on a single line? No. The working space has no \n but is considered as a line. Use H,G,N.


Let's examinate your code:

sed '/^$/!{ smile you said "If the line is not an empty line". Why not saying "If there is something": sed '/./{ ?
h smile Great to put into holding space. But if you never get the text back, it is useless.
N Remember that the cycle is accomplished for each line and then, a new cycle starts. Here, it will do what you want one line out of two. Because it has sent result to screen before a new N is executed.


Still any problem? winky smile
blarneyme (MIS)
29 Mar 12 8:02
Thank you very much for your answer. It is very clear and very understandble.
FlorianAwk (Programmer)
30 Mar 12 1:35
More powerfull:

sed ':l N;s/\(.*\)\([A-Z]\) \(.*\)\n\2 \(.*\)/\1\2 \3,\4/;b l' test.txt

:l
It is a label. It could have been:
:yahoo

b l
It is an unconditionnal branching.
When does it stop? When 'N' has no line to provide.
If you used :yahoo, use:
b yahoo

Is there any conditionnal branching? Yes:
t yahoo
This command loops when the last substitution has matched

winky smile
blarneyme (MIS)
30 Mar 12 6:59
Very succinct indeed! Would you be willing to provide me with an example of using conditonal branching (t yahoo)?

Thanks!
FlorianAwk (Programmer)
30 Mar 12 14:15

CODE

#define VAR_3_SPACES    "   "
#define VAR_4_SPACES    "    "
#define VAR_5_SPACES    "     "

pdhfnvb
:kdfjvn:df
:kdjfvn:dkvn
:kdjfvn:

CODE

sed 's/"$/\n"/;:loop s/"\n/"/;s/ \n/\nQ/;t loop' qqq.txt

CODE

#define VAR_3_SPACES    "QQQ"
#define VAR_4_SPACES    "QQQQ"
#define VAR_5_SPACES    "QQQQQ"

pdhfnvb
:kdfjvn:df
:kdjfvn:dkvn
:kdjfvn:

The first substitution inits the process.
The second will match only at the end.
The third has to be repeated. Why? Because if a pattern is recognized once, sed won't work on it twice. => loop
There is no stopping command => conditional branching
PHV (MIS)
30 Mar 12 15:17
FlorianAwk, your sed script posted 30 Mar 12 14:15 is valid only with GNU sed ...
Did you try it with a legacy *nix sed ?
FlorianAwk (Programmer)
30 Mar 12 17:01
No,I didn't.
But if you read the UNIX man pages, http://unixhelp.ed.ac.uk/CGI/man-cgi?sed
you can find label, b and t. Everything should work. I wonder how you see the difference.

Does it work better with
\"
instead of
"
?
PHV (MIS)
30 Mar 12 17:38
In legacy sed:
1) the : command is limited to a 8 length label and don't admit ; as a command delimiter (work around: replace ; with ^J)
2) \n in a pattern is considered as n (no workaround AFAIK)

Hope This Helps, PH.
FAQ219-2884: How Do I Get Great Answers To my Tek-Tips Questions?
FAQ181-2886: How can I maximize my chances of getting an answer?

FlorianAwk (Programmer)
30 Mar 12 18:47
Have you read the link I gave? You could read

CODE

REGULAR EXPRESSIONS
(...)  The \n sequence in a regular expression matches the newline character, and similarly for \a, \t, and other sequences.
Can you give official origin of your information? Would you say UNIX man pages are bad?

Furthermore, in my script, \n could have been any character. It works.
PHV (MIS)
30 Mar 12 22:43
Have you read the link I gave
Yes.
And a man page saying that a command admits long option (--anything) isn't a UNIX man man page but a GNU one.

Reply To This Thread

Posting in the Tek-Tips forums is a member-only feature.

Click Here to join Tek-Tips and talk with other members!

Back To Forum

Close Box

Join Tek-Tips® Today!

Join your peers on the Internet's largest technical computer professional community.
It's easy to join and it's free.

Here's Why Members Love Tek-Tips Forums:

Register now while it's still free!

Already a member? Close this window and log in.

Join Us             Close