问题
$ cat file
aaa bbb ccc
ddd eee
jjj kkk lll
mmm
nnn ooo ppp
The following AWK command will paste the 'mmm' line at the end of the 'ddd eee' line. Is there a simpler way to do this using AWK or sed?
$ awk 'FNR==NR {if (NR==4) foo=$0; next} FNR==2 {print $0" "foo; next} FNR==4 {next} 1' file file
aaa bbb ccc
ddd eee mmm
jjj kkk lll
nnn ooo ppp
To clarify: I want to paste line 4 at the end of line 2 in this particular file, with a single space between the 'ddd eee' and the 'mmm'. That's the task. Is there an AWK or sed solution that's simpler than the one I came up with?
回答1:
This can be done in sed
using the hold space:
sed '2{N;h;N;s/\n.*\n/ /;p;g;D;}' file
2{...}
Run the enclosed commands on line two.N;h;N
Read next two lines into the pattern space, holding the first two.s/\n.*\n/ /
Substitute a space for the middle line.p;g;D
Print the pasted lines, load the hold space, and delete the first line (leaving the one that was removed by the previous substitute).
or using captures (\(...\)
) & back-references (\1
, \2
, etc.):
sed '2{N;N;s/\(\n.*\)\n\(.*\)/ \2\1/;}' file
2{...}
Run the enclosed commands on line two.N;N
Read next two lines into the pattern space.s/\(\n.*\)\n\(.*\)/ \2\1/
Swap the third and fourth line, joining the first and third lines.\(\n.*\)
Capture the third line, including the leading newline.\n\(.*\)
Capture the fourth line, excluding the leading newline./ \2\1/
Replace the matched portion (the third & fourth lines) with a space, followed by the second, and then the first capture groups.
回答2:
This meets the letter of the amended problem statement — it prints line 1, appends line 4 after the content of line 2 as line 2, then prints line 3, and then prints line 5 and beyond:
awk 'NR == 1 || NR >= 5 { print; next }
NR == 2 { save2 = $0 }
NR == 3 { save3 = $0 }
NR == 4 { print save2, $0; print save3 }' file
It's simpler than the code in the question in that it only scans the file once.
The output:
aaa bbb ccc
ddd eee mmm
jjj kkk lll
nnn ooo ppp
回答3:
Solution in TXR:
$ txr -c '@line1
@line2
@line3
@line4
@(data rest)
@(output)
@line1
@line2 @line4
@line3
@ (repeat)
@ rest
@ (end)
@(end)' file
aaa bbb ccc
ddd eee mmm
jjj kkk lll
nnn ooo ppp
回答4:
This is simpler:
$ awk 'FNR==NR {if (NR==4) foo=$0; next} FNR==2{$0=$0" "foo} FNR!=4' file file
aaa bbb ccc
ddd eee mmm
jjj kkk lll
nnn ooo ppp
Other solutions might be faster or use less memory but they won't be simpler.
来源:https://stackoverflow.com/questions/39187856/awk-or-sed-way-to-paste-non-adjacent-lines