Reputation: 5509
i am working with a task right now, manipulating text in Unix, but i have no idea how i will do it. I am planning to use sed. this is wat i am trying to do.
I have this text.
BS111
xxxxx
yyyyy
zzzzz
BS112
xxxxx
yyyyy
zzzzz
BS113
xxxxx
yyyyy
zzzzz
so on.. with this kind of format
and i want it to be like:
BS111 xxxxx
BS111 yyyyy
BS111 zzzzz
BS112 xxxxx
BS112 yyyyy
BS112 zzzzz
BS113 xxxxx
BS113 yyyyy
BS113 zzzzz
so on.. with this kind of format
the BS* and its data occurs almost hundred times. so i think the best way to do it is to use a script. thank you in advance for your help.
Upvotes: 3
Views: 268
Reputation: 2524
try awk
awk '/^BS/{i=$0; next;} {if(length($0)) printf("%s ",i); print $0}' <filename>
Update:
'/^BS/{i=$0; next;} {if(length($0)) printf("%s ",i); print $0}' remember, in awk, {...}
denotes a set of action. /pattern/{...}
means if a pattern is found, do {...}
actions.
/^BS[0-9]/
will search for pattern in each line. If the pattern is found, i
(variable in awk) will be updated with the pattern ($0 is complete line) and next
will immidiately move to next line.So next set of action in {if(...}
will be skipped if a pattern is found. So i
will always contain the last pattern value and if a line is containing pattern, except updating i, next set of action will not take place for the line.
Next set of action is, if(length($0))
if, the line contains text, printf("%s ",i); print the last found pattern, And then
print $0prints the original line. So for an empty line, only an empty line is printed, if some text is there, first the
ior
last found pattern` is printed, then the original line is printed. Btw, sputnick's solution is also doing the same thing, only in a more compact form. So you can dissect that one also for fun. Hope i am clear, please feel free to ask anything you need to know
Upvotes: 2
Reputation: 6258
In sed you can do:
sed -n -r '/^BS[0-9]{3}/{h;d};/./G;s/(.*)\n(.*)/\2 \1/p' test.txt
-n
means sed wont output anything unless told to by the p
command.
-r
means using extended regular expressions.
/^BS[0-9]{3}/{h;d}
matches a line starting with BS and three numbers, the h
command puts the pattern into the holding buffer (copies it for later insertion). The d
command deletes the matched line.
/./G
matches any line. The G
command appends the content of the holding buffer (in this case BSxxx). s/(.*)\n(.*)/\2 \1/p
matches the current and the next line, switches them and removes the newline. And finally the p
command prints the resulting line
Upvotes: 1
Reputation: 58351
This might work for you (GNU sed):
sed -r '/^BS/{h;d};/./!b;G;s/(.*)\n(.*)/\2 \1/' file
Upvotes: 3
Reputation: 184965
With awk :
awk '/^BS/{v=$0;next} {print (/^$/) ? $0 : v, $0}' file.txt
BS111 xxxxx
BS111 yyyyy
BS111 zzzzz
BS112 xxxxx
BS112 yyyyy
BS112 zzzzz
BS113 xxxxx
BS113 yyyyy
BS113 zzzzz
Upvotes: 3