Answers:
使用awk
和整数数学:
awk 'NR%3 == 1 { print } NR%3 == 2 { delay=$0 } NR%3 == 0 { print; print delay; delay=""} END { if(length(delay) != 0 ) { print delay } }' /path/to/input
模运算符执行整数除法并返回余数,因此对于每一行,它将返回序列1、2、0、1、2、0 [...]。知道了这一点,我们只是将输入保存在模数为2的行上,以备以后使用,也就是在输入为零时打印输出。
NR%3 == 0 { print; print delay; delay=""} END { if(length(delay) != 0 ) { print delay }
。
$ seq 9 | sed -n 'p;n;h;n;G;p'
1
3
2
4
6
5
7
9
8
就是说,p
使当前行变粗,获得前一个n
扩展名,h
使其变旧,获得最前n
一个扩展名,G
然后保留行(将其追加到模式空间),并p
用两行第三行和第二行交换该行的模式空间。
另一种awk方法:
awk '{print $0; if ((getline L2)>0 && (getline L3)>0){ print L3 ORS L2 }}' file
输出:
gi_1234
I have a cat.
My cat is blue.
gi_5678
I also have a dog.
My dog is orange.
(getline L2)>0 && (getline L3)>0
-提取接下来的2条记录(如果存在)
每个第二和第三条记录分别分配给L2
和L3
变量
line2
,等
使用perl
和一个简短的脚本:
user@pc:~$ cat input.txt
gi_1234
My cat is blue.
I have a cat.
gi_5678
My dog is orange.
I also have a dog.
user@pc:~$ perl -ne '$l2=<>; $l3=<>; print $_,$l3,$l2;' input.txt
gi_1234
I have a cat.
My cat is blue.
gi_5678
I also have a dog.
My dog is orange.
该脚本会处理整个文件,对于每一行(存储在中$_
),它将获取接下来的两行($l2
和$l3
),并按照请求的顺序打印它们:line1,line3,line2。
一种方法可能如下:
sed -e '
/\n/s/\(.*\)\(\n\)\(.*\)/\3\2\1/;//b
$!N;$q;N; # load up the pattern space with 3 lines provided eof not reached
P;D; # first just print the first line then interchange the two and print them
' yourfile
或者,
perl -ne 'print $_, reverse scalar <>, scalar <>' yourfile
gi_1234
I have a cat.
My cat is blue.
gi_5678
I also have a dog.
My dog is orange.
perl -ne 'print if $.%3==1;$var=$_ if $.%3==2;print $_ . $var if $.%3==0' input.txt
这里的想法是,我们使用%
带有行号$.
变量的模运算符,以找出哪个是第一行,哪个是第二行,哪个是第三行。对于第三行,余数为0,而对于第一行和第二行,它将有相应的数字。
测试:
$ cat input.txt
gi_1234
My cat is blue.
I have a cat.
gi_5678
My dog is orange.
I also have a dog.
$ perl -ne 'print if $.%3==1;$var=$_ if $.%3==2;print $_ . $var if $.%3==0' input.txt
gi_1234
I have a cat.
My cat is blue.
gi_5678
I also have a dog.
My dog is orange.
将第二行存储到变量中的方法存在缺陷。如果最后一行是“第二”行,即该行号的余数是2怎么办?My dog is orange
如果我们省略最后一行,我和DopeGhoti的答案中的原始代码将不会打印。两种情况下的解决方案都是使用END{}
代码块,并在打印后取消设置临时变量。换一种说法:
$ awk 'NR%3 == 1 { print } NR%3 == 2 { delay=$0 } NR%3 == 0 { print; print delay;delay=""}END{print delay}' input.txt
和
$ perl -ne '$s=$_ if $.%3==2;print $_ . $s and $s="" if $.%3==0 or $.%3==1;END{print $s}' input.txt
这样,代码将适用于文件中任意数量的行,而不仅仅是被3整除的行。
在awk的情况下,如果文件的最后一行产生$的输出1。%3,由于无条件打印,前面的代码存在输出空白换行符的问题END{print delay}
,因为print
注释中提到的函数始终将换行符附加到要操作的任何变量上。如果是perl
版本,则不会发生此问题,因为带有-ne
标志print
功能不会附加换行符。
尽管如此,awk的解决方法是使条件语句成为条件,正如Dope Ghoti在评论中所提到的那样,是为了验证临时变量的长度。相同修复程序的perl版本为:
$ perl -ne '$s=$_ if $.%3==2;print $_ . $s and $s="" if $.%3==0 or $.%3==1;END{print $s if length $s}' input.txt
awk
)的答复纳入您的改进中,从而解决了此问题NR%3 == 0 { print; print delay; delay=""} END { if(length(delay) != 0 ) { print delay }
。
-ne
标志的打印不会输出换行符。它确实可以打印,但是它是一个空字符串,没有尾随换行符。但是,我在回答中添加了对该问题的提及和相同的解决方法。谢谢 !