sed:如何將文字加入前x個出現的位置

sed:如何將文字加入前x個出現的位置

我正在嘗試將文字添加到行的前 x 次出現的末尾。我知道如何在全球範圍內以及在第 n 次發生時執行此操作。我不知道如何在前 n 次出現時執行此操作。一個範例是包含以下內容的 text.txt 檔案:

This is a test
junk
This is a test
More junk
This is a test
This is a test
This is a test

而且,我想加一個“.”在前三次結束時出現“這是一個測試”。我想要得到的輸出是:

This is a test.
junk
This is a test.
More junk
This is a test.
This is a test
This is a test

答案1

This.*test是正確的正規表示式。星號表示“前一個字元的 0 次或多次”,因此This*test不會與您的任何行相符。

現在,Sed 不擅長算術。對於一些優雅的東西,我建議 Awk:

awk '/This.*test/{c++};{print $0 (c<4 ? "." : "")}' file

我認為只要說c,就像 Awk 中任何未設定的變數一樣,都被視為零,但如果您需要進一步說明,請告訴我。

答案2

另一種變體可以避免在找到所有 3 個匹配項後進行正規表示式匹配:

awk -v n=3 'n && /This is a test/ {n--; $0 = $0 "."}; {print}'

具體sed而言,您可以執行以下操作:

sed '
  1 {
    x
    s/^/.../
    x
  }
  /This is a test/ {
    s/$/./
    x
    s/.//
    /./ {
      x
      b
    }
    g
    :1
    $! {
      n
      b 1
    }
  }'

我們追蹤要附加的 s 數量,作為保留空間中.相應的 s 數量。.

不用說,這sed對於此類任務來說不太合適。如果想要的原因sed是為了-i在一些實作上找到就地編輯的擴充(借自perl),請注意,GNU 實作awk也可以使用 1 來實現-i /usr/share/awk/inplace.awk,或者您可以使用真實的東西:

perl -lpi -e '
  if ($n < 3 && /This is a test/) {
    $n++;
    $_ .= ".";
  }' your-file

如果您想.在每次出現 後添加 ,This is a test而不是在所有包含至少一次出現 的行之後添加This is a testperl也將是最佳選擇:

perl -pi -e 's{This is a test\K}{$n++ < 3 ? "." : ""}ge' your-file

^不使用-i inplaceas嘗試先從目前工作目錄gawk載入inplace擴充功能(asinplace或),有人可能已經在其中植入了惡意軟體。隨系統提供的擴展inplace.awk的路徑可能會有所不同,請參閱輸出inplacegawkgawk 'BEGIN{print ENVIRON["AWKPATH"]}'

答案3

我們perl可以如圖所示

perl -lpe '
  $_ = $k == 3 ? next : s/This is a test(?{$k++}).*\K/./r;
' file

大像也會跳舞,儘管舞步很簡單。使用GNU sed擴展正規表示式模式下的寫入,-E 我們可以將計數儲存為保留中的換行符數量。

K=3
sed -Ee '
  /This is a test/!b
  G
  /(.*\n){'"$K"'}.*\n/!{
    s/\n+/./p;z;H;d
  }
  s/\n+//
  :a;n;ba
' file

相關內容