-3

I have in a file sth like:

....
sth
Q-[N1] your name?
A1-My first name is Joe
A2-My Last name is  Jim
sth
sth
....
....
sth
Q-[N2] your name?
A1-My first name is Jack
A2-My Last name is  JUNE
sth
sth
....

I wanted to add "last name" at the end of the line started with Q-. Is it possible to do that in Perl, sed, awk, grep? The transformed file looks like:

....
sth
Q-[N1] your name? **Jim**
A1-My first name is Joe
A2-My Last name is  Jim
sth
sth
....
....
sth
Q-[N2] your name? **JUNE**
A1-My first name is Jack
A2-My Last name is  JUNE
sth
sth
....
rook
  • 5,880
  • 4
  • 39
  • 51
Nukas
  • 3
  • 1
  • 3
    You'll probably get a better response if you try something. Literally, the answer to your question is "yes". So you need to ask a better question. –  Mar 31 '16 at 10:29

4 Answers4

1

This solution does not actually use multi line patterns but only looks for the first line (the Q-... your name? part) and loads the next two lines into the pattern space. Then it does some substitution on this (three line) pattern space with simple regex to get the desired output.

sed '/^Q-\[N[[:digit:]]*\] your name?/ {
  N
  N
  s/\( your name?\)\(.* Last name is *\)\(.*\)$/\1 **\3**\2\3/
}' < file
Lucas
  • 685
  • 4
  • 19
  • I'm not great with sed, but doesn't the question mark need to be escaped? – Borodin Mar 31 '16 at 11:36
  • In some variants of regex the question mark is a special character but that does not seem to be the case with `sed` (without the `-E` option). Try `echo '?' | sed 's/?/x/'` and `echo '?' | sed -E 's/?/x/'`. – Lucas Mar 31 '16 at 11:38
  • I don't have a Linux terminal at hand, but that's unambiguous anyway. I would want to see what `echo 'ab?' | sed 's/b?/x/'` does – Borodin Mar 31 '16 at 11:43
  • It is not "unambigous anyway" as the version with `-E` gives an error message: `sed: -e expression #1, char 6: Invalid preceding regular expression`. Your command prints this: `echo 'ab?' | sed 's/b?/x/'` -> `ax` and `echo 'ab?' | sed -E 's/b?/x/'` -> `xab?` (because *zero* or more "b"s are matched at the start of the string). – Lucas Mar 31 '16 at 11:48
  • The latter is what I was expecting. I have never heard of the `-E` option, and the answer to [*Whats the difference between sed -E and sed -e*](http://stackoverflow.com/questions/3139126/whats-the-difference-between-sed-e-and-sed-e) indicates that it's an undocumented request for compatibility with *FreeBSD*. This has been interesting, if OT. Thank you – Borodin Mar 31 '16 at 12:05
  • A `?` is the ERE metacharacter for zero-or-more repetitions of the preceding regexp token. sed by default operates on BREs, not EREs which is why the `?` does not need to be escaped above. If you DID escape it then in some versions of sed, e.g. GNU sed, that would activate it's ERE property which is the opposite of what you want. If you added the `-r` argument then your command would be using EREs and so the `?` then would have to be escaped to deactivate it's ERE property. Yes, its a minefield :-). – Ed Morton Mar 31 '16 at 13:07
  • I need to add \ at the end of each line to make it works, Thanks your help. – Nukas Mar 31 '16 at 16:17
  • 1
    @EdMorton: Thanks for the clarification. This sounds like the bad old days of HTML., but with far more severe consequences. Someone like ISO must adopt the most comprehensive functionality (Perl's?) and make it their own – Borodin Mar 31 '16 at 16:38
  • 1
    @Borodin you're welcome. Maybe ISO could standardize CSV while they're at it and save a lot of people a lot of problems :-) ! – Ed Morton Mar 31 '16 at 17:37
1
use strict;
use warnings 'all';

our @ARGV = 'name_is_joe.txt';

my $data = do {
    local $/;
    <>; 
};

$data =~ s/^(Q-.+)(\n^A1-.+\n^A2-.+\bis\s+(.+)\n)/$1 $3$2/gm;

print $data

output

....
sth
Q-[N1] your name? Jim 
A1-My first name is Joe
A2-My Last name is  Jim
sth
sth
....
....
sth
Q-[N2] your name? JUNE 
A1-My first name is Jack
A2-My Last name is  JUNE
sth
sth
....

Or as a one-liner

perl -0777 -pe 's/^(Q-.+)(\n^A1-.+\n^A2-.+\bis\s+(.+)\n)/$1 $3$2/gm' myfile
Borodin
  • 126,100
  • 9
  • 70
  • 144
0

awk to the rescue! (with tac)

$ tac file | 
  awk '/My Last name is/{n=$NF} /^Q-/{$0=$0 FS "**"n"**"}1' | 
  tac

....
sth
Q-[N1] your name? **Jim**
A1-My first name is Joe
A2-My Last name is  Jim
sth
sth
....
....
sth
Q-[N2] your name? **JUNE**
A1-My first name is Jack
A2-My Last name is  JUNE
sth
sth
....
karakfa
  • 66,216
  • 7
  • 41
  • 56
0

You could first translate newline to ;, then do sed search and replace; last translate ; back to newline. Please try:

cat temp | tr '\n' ';' | sed -r 's/(your\s+name\?)(;A1-[^-]*-My\s+Last\s+name\s+is\s+)(\w+)/\1 \3\2\3/g' | tr ';' '\n'

Output:

....
sth
Q-[N1] your name? Jim
A1-My first name is Joe
A2-My Last name is  Jim
sth
sth
....
....
sth
Q-[N2] your name? JUNE
A1-My first name is Jack
A2-My Last name is  JUNE
sth
sth
....
Quinn
  • 4,394
  • 2
  • 21
  • 19