當替換命令寫入檔案時,sed 僅替換檔案的偶數行

當替換命令寫入檔案時,sed 僅替換檔案的偶數行

我將所有替換命令都放在一個檔案中(例如replace.sed),並將其與sed 的-f 標誌一起使用(sed -f Replace.sed InputFile)。但現在我遇到了一種情況,我需要僅在給定輸入檔案的偶數行上應用這些替換規則(即僅在第 2,4,6 行等)。文件也被其他腳本使用。

答案1

使用進程替換來sed動態調整檔案中的命令:

$ cat replace.sed
s#foo#bar#

$ printf "foo\nfoo\nfoo\nfoo\n" | sed -f replace.sed
bar
bar
bar
bar

$ printf "foo\nfoo\nfoo\nfoo\n" | sed -f <(sed 's#^#2~2#g' replace.sed)
foo
bar
foo
bar

答案2

sed -f <(sed -e 's/.*/2~2{&;}/' replace.sed) InputFile

答案3

其他答案試圖告訴您的是使用sed的地址形式:first~step

地址

    … 支援以下地址類型: …

    第一的
      匹配每一個'以 line 開頭的行第一的。例如,「sed -n 1~2p」將列印輸入流中的所有奇數行,位址「2~5」將從第二行開始符合每五行。  第一的可以為零;在這種情況下, sed操作就好像它等於 。 (這是一個擴展。)

顯而易見的解決方案是在每個命令之前加上replace.sedwith 2~2 (或者0~2,如果它在您的版本中工作sed),以使命令在每隔一行上運行,從第二行開始(即輸入流中的所有偶數行,按照您的要求)。但你說你不能修改replace.sed。好吧,下一步(如其他答案所確定的,但沒有解釋)是使用 shell 的流程替代功能,其行為就像一個文件,是.如果,正如您的問題所示, 只是一系列簡單的替代命令,那麼 <(command_list)command_listreplace.sed

sed -f <(sed 's/^/2~2/g' replace.sed)

應該管用。

但這有缺點:

  • 如果每行有多個命令,則上述內容只會影響每行的第一個命令。
  • 如果您有帶有數字地址的命令(例如,42s/Zaphod/Beeblebrox/),它們將被轉換為,例如,轉換為2~242…,結果顯而易見。
  • 如果您的命令帶有非數位位址(例如,/windows/s/command/cmd/),則上述命令將徹底失敗。

如果出現任何這些情況,您應該使用

sed -f <(sed -e 's/.*/2~2{&;}/' replace.sed)

sed每行上的所有命令放入一個命令組的變體。

replace.sed但如果有多行命令,即使這樣也會失敗。

基於上述想法,我想出了

sed -f <(echo '0~2{'; cat replace.sed; echo '}')

這使得全部的 replace.sed文件到命令組。在我的表面測試中,這似乎解決了我對其他解決方案提出的擔憂。如果它有一個很長replace.sed或非常複雜的命令的問題,我不會感到震驚。

相關內容