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