更改文件中的行顺序

更改文件中的行顺序

我正在尝试更改特定模式中的行顺序。处理包含多行(例如 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打印当前行,获取next 行,h旧它,获取next 行,Get 保留的行(将其附加到模式空间)并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 -neflagsprint函数不会附加换行符。

尽管如此,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 

相关内容