將特定行從一個位置移動到另一個位置
我正在使用 ubuntu 終端,我需要將文件中的特定行(第 11 個位置)移動到第一行,然後將最終結果傳輸到新文件中。原始文件包含數百行。
到目前為止,我嘗試使用 sed 命令工具,但沒有達到我想要的效果。這是我到目前為止得到的:
[mission 09] $ sed -n -e '1p' -e '11p' bonjour > bonjour2
但它只顯示新文件的第一行和第 11 行。但我希望新文件在其餘原始行中具有所需的修改位置。
輸入 :
English: Hello Turkish: Marhaba Italian: Ciao German: Hallo Spanish: Hola Latin: Salve Greek: chai-ray Welsh: Helo Finnish: Hei Breton: Demat French: Bonjour
期望的輸出
French: Bonjour English: Hello Turkish: Marhaba Italian: Ciao German: Hallo Spanish: Hola Latin: Salve Greek: chai-ray Welsh: Helo Finnish: Hei Breton: Demat
有什麼建議嗎?
sed -n '1h;2,10H;11G;11,$p'
h
第一行,因為新行而複製,然後追加H
到 10。在第 11 行,獲取保持空間
從11 點到結束,列印。
]# sed -n '1h;2,10H;11G;11,$p' bonj French: Bonjour English: Hello Turkish: Marhaba Italian: Ciao German: Hallo Spanish: Hola Latin: Salve Greek: chai-ray Welsh: Helo Finnish: Hei Breton: Demat
這更好:
]# seq 20 | sed -n '1h;2,10H;11G;11,$p' 11 1 2 3 4 5 6 7 8 9 10 12 13 14 15 16 17 18 19 20
我舉你的例子:
]# sed -e 1p -e 11p -n bonj English: Hello French: Bonjour
…
-n
最後的開關只是為了顯示它對兩個表達式都很重要。我也有
-n
, 然後1h;2,10H
,應該只是1,10H
,這是一個行號範圍和一個“保持”(儲存)命令。什麼都沒有列印出來。
11,$p
是另一個範圍。在第 11 行,它列印了剛剛從保持中返回的“11G”(即 1-10)並附加到第 11 行。第 12 行直到 $ 只是列印自己,因為
-n
.我應該
-e
像你一樣做兩個:sed -n -e '1h;2,10H' -e '11G;11,$p'
從 1,10 開始,保留,從 11 開始,$ 是列印。
第 11 行有第
G
一個,然後是p
. 這很重要,因為:]# seq 20 | sed -n -e '1h;2,10H' -e '11,$p;11G' 11 12 13 14 15 16 17 18 19 20
這裡第 12 行清除了第 11 行在列印後得到的內容。
作為帶有參數的函式
總是第 11 行對函式“putfirst”很無聊:
]# declare -f putfirst putfirst () { e="1h;2,$(($1-1))H;${1}G;${1},\$p"; sed -ne "$e" $2 }
兩個步驟:字元串生成,然後是 sed 呼叫。“$”有兩種含義:“p”不是變數!
這是有效的最低數字:
]# seq 7 | putfirst 3 3 1 2 4 5 6 7
或者使用原始的“bonj”文件:
]# putfirst 4 bonj | putfirst 6 |head -4 Latin: Salve German: Hallo English: Hello Turkish: Marhaba
這是連續兩個sed,但是現在做兩個操作。
Perl
perl -ne '$n++; $h.=$_ if $n<11; print $_.$h if $n==11; print if $n>11' <(seq 20)
作為一些腳本,它採用文件名並且不需要選項:
$want=11 ; while (<>) { $n++ ; if ($n < $want) # before $want: store line { $lowlines .= $_ ; next } # next line (avoids 'else') if ($n == $want) # at line $want: append stored lines to $_ { $_ .= $lowlines } print ; # print $_ for $n not less than $want }
AWK(從 Ed 那裡偷來的(不是編輯!))
NR < 11 { buf[NR] = $0; next } NR >=11 { print if (NR == 11) { for (i=1; i<11; i++) { print buf[i] } } }
我使用
NR
而不是遞增n
,並使流程更加明確。相同的“技巧”:next
簡化下游。和
perl -n
$n++ ; $tmp = $tmp . $_ if $n < 11 ; print $_ . $tmp if $n == 11 ; print $_ if $n > 11 ;
這是最好的格式。對稱的。
使用(和派生
ed
的行編輯器):sed``grep
printf '%s\n' '11m0' 'w bonjour2' 'q' | ed -s bonjour
這會將編輯命令應用於
11m0
將第 11 行移動到第一行之前的文件。然後它將生成的文件寫入文件bonjour2
並退出。或者:
printf '%s\n' '11m0' ',p' 'Q' | ed -s bonjour >bonjour2
…而不是使用命令寫入特定文件,而是
ed
將整個文件列印到標準輸出。然後將結果重定向到一個新的文件名。該,p
命令(縮寫為1,$p
)會將整個文件輸出到標準輸出並Q
強制退出(即使文件已更改)。要就地更改文件(即更改原始文件),請將結果寫回文件本身:
printf '%s\n' '11m0' 'wq' | ed -s bonjour
上述變體之一的範例執行:
$ printf '%s\n' '11m0' ',p' 'Q' | ed -s bonjour >bonjour2 $ cat bonjour2 French: Bonjour English: Hello Turkish: Marhaba Italian: Ciao German: Hallo Spanish: Hola Latin: Salve Greek: chai-ray Welsh: Helo Finnish: Hei Breton: Demat
要始終將最後一行移到頂部,請使用
$m0
.11m0
要始終移動以字元串開頭的行French:
,請使用/^French:/m0
.