更改文件中的行順序

更改文件中的行順序

我正在嘗試更改特定模式中的行順序。處理包含多行(例如 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 

相關內容