Swapping three lines

I have some text:

  <date>some_date</date>
  <text>some_text</text>
    <name>some_name<name>

and I want to transform it to smthng like that:

some_name on some_date: some_text

I've tried sed:

sed 's/<text>\(.*\)<\/text>
<name>\(.*\)<\/name>/\2 - \1/'

but it says unterminated substitute pattern, and I can't understand why... :slight_smile:

so, I would be very grateful if someone could point me to the right direction :).

thank you.

perl -ln0e '/<date>(.+?)<\/date>.*?<text>(.+?)<\/text>.*?<name>(.+?)<\/name>/s;print "$3 on $1: $2"' file
1 Like

thanks! but now it only changes the first array of data, operates with the first three lines (and I have a lot of all those <date></date><text></text><name></name>).

so, I wonder, how to make it to operate with the whole input, is there some kind of global switch?

perl -ln0e 'while(/<date>(.+?)<\/date>.*?<text>(.+?)<\/text>.*?<name>(.+?)<\/name>/sg){print "$3 on $1: $2"}' file

great, thank you!

now I've just should figure for myself what all those mysterious perl switches do :).

This is because you spread the command over two lines and you cannot do that like this.. Also, this command would not work since sed is line based, you would have to join the next lines with the N command, e.g.:

sed '/<date>/{N;N;s|.*<date>\(.*\)</date>.*<text>\(.*\)</text>.*<name>\(.*\)</name>.*|\3 on \1: \2|}' infile

output:

some_name on some_date: some_text
1 Like

but I can split the substitute pattern over two lines with sed. e.g.:

sed 's/\([0-9A-Za-z]\),\([0-9A-Za-z]\)/\1 \
\2/g'

so, I probably cannot split search pattern, that's why I saw that error?

You saw the error because you did not terminate the first line of your command with a \

no, backslash doesn't help:

dsjkvf on Penelope @ ~/tmp/devel> cat data 
<date>some_date</date>
<text>some_text</text>
<name>some_name</name>
dsjkvf on Penelope @ ~/tmp/devel> echo data | sed 's/<text>\(.*\)<\/text>\
<name>\(.*\)<\/name>/\2 - \1/'
sed: 1: "s/<text>\(.*\)<\/text>\ ...": unterminated substitute pattern

Hmm, I get:

$ cat data
  <date>some_date</date>
  <text>some_text</text>
    <name>some_name</name>
$ cat data | sed 's/<text>\(.*\)<\/text>\
<name>\(.*\)<\/name>/\2 - \1/'
  <date>some_date</date>
  <text>some_text</text>
    <name>some_name</name>
$ cat data| sed 's/<text>\(.*\)<\/text>
<name>\(.*\)<\/name>/\2 - \1/'
sed: -e expression #1, char 22: unterminated `s' command

So no error message. Are you on Solaris?
Is the backslash the last character on the line?

I'm on Mac OS X 10.5.8 :).

however, if I use GNU sed version 4.1.5 (from ports) then, yes, it works without errors, but also without any results, I'd say: the sed command above we were testing should output:

some_name - some_text

, but it just prints the contents of the file 'data' without applying any filters.

where am I wrong?

Hi, as I wrote in my first post, this command would not work since sed is line based, you would have to join the next lines with the N command (I gave an example).

so, as I supposed after your first answer, it seems that it just can't use a two-line search pattern, but can only operate split lines as a substitute pattern.