Alice Everett
Alice Everett

Reputation: 375

specific string replacements using linux commands

I have data in the following form:

<some text0>
<text1> <text2> .
<some text1>
<text3> <text4> .

Now I want to convert this data into the following form:

<text1> <text2> <some text0>.
<text3> <text4> <some text1>.

I know I can do it using C++, but is there some way of doing this using linux. I know sed is good at replacing characters...but I am not getting as to how should I use sed to do replacements of the above form.

Upvotes: 0

Views: 87

Answers (5)

Jotne
Jotne

Reputation: 41460

Simple and understandable awk

awk '{a=$0;getline;b=$NF;$NF="";print $0 a b}'
<text1> <text2> <some text0>.
<text3> <text4> <some text1>.

a=$0 Store first line in variable a
getline Get the next line b=$NF Store the last field in b (the .) $NF="" Clear the last field print $0 a b Print this line, previous line and b (the .)

Upvotes: 0

NeronLeVelu
NeronLeVelu

Reputation: 10039

sed "N;s/\(.*\)\n\(.*\) \.$/\2 \1./" YourFile

sed read 1 line at a time by default into a working buffer and print the content at end of process starting next line to process.

N : add a \n to the buffer than load the next line of input

s/Part1/Part2/ : take begining of the buffer until \n, the \n than everything until the . before the end($) and rewrite it in different order \1 \2 are respectively content of 1st and second group (a group is the content found matching element between ( and ) in first part of s/Part1/Part2/)

note that \ is used here mainly for escaping next char due to shell substitution between " " and . mean "dot"

Upvotes: 2

Kent
Kent

Reputation: 195239

this one-liner works for your example:

kent$  awk '!/\.$/{s=$0;next}sub(/\.$/,s".")' f
<text1> <text2> <some text0>.
<text3> <text4> <some text1>.

explanation:

awk               #the program
!/\.$/{s=$0;next} #if the line was not ending with dot(.),
                  #assign it to s, read next line
sub(/\.$/,s".")   #we are here when the line ends with ".",
                  #then we replace ending "." with s, and print.
f                 #the input file

Upvotes: 2

glenn jackman
glenn jackman

Reputation: 247202

I would use awk, but here's a long pipeline for contrast

sed 's/\.$//' <<END | tac | paste -d " " - - | tac | sed 's/$/./'
<some text0>
<text1> <text2> .
<some text1>
<text3> <text4> .
END    sed 's/\.$//' <<END | tac | paste -d " " - - | tac | sed 's/$/./'
<some text0>
<text1> <text2> .
<some text1>
<text3> <text4> .
END
<text1> <text2>  <some text0>.
<text3> <text4>  <some text1>.

Upvotes: 0

Chris Seymour
Chris Seymour

Reputation: 85883

By redefining the record seperator with gawk:

$ awk 'NR>1{print $1,$2,R $3}{R=RT}' RS='<some text[^>]>' file
<text1> <text2> <some text0>.
<text3> <text4> <some text1>.

Upvotes: 0

Related Questions