我正在尝试更改特定模式中的行顺序。处理包含多行(例如 99 行)的文件。对于每三行,我希望第二行成为第三行,第三行成为第二行。
例子。
1- 输入:
gi_1234
My cat is blue.
I have a cat.
gi_5678
My dog is orange.
I also have a dog.
...
2-输出:
gi_1234
I have a cat.
My cat is blue.
gi_5678
I also have a dog.
My dog is orange.
...
答案1
$ seq 9 | sed -n 'p;n;h;n;G;p'
1
3
2
4
6
5
7
9
8
也就是说,p
打印当前行,获取n
ext 行,h
旧它,获取n
ext 行,G
et 保留的行(将其附加到模式空间)并p
打印 2 行模式空间,其中第三行和第二行交换。
答案2
使用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 的行上以备后用——也就是说,在输入为零时打印输入。
答案3
使用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。
答案4
珀尔
perl -ne 'print if $.%3==1;$var=$_ if $.%3==2;print $_ . $var if $.%3==0' input.txt
这里的想法是,我们使用%
带有行号$.
变量的模运算符,来计算出哪个是第一个,哪个是每秒,哪个是每第三行。每第 3 行余数为 0,而每第 1 行和第 2 行都有相应的数字。
测试:
$ 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
版本,则不会出现此问题,因为 with -ne
flagsprint
函数不会附加换行符。
尽管如此,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