我正在嘗試將文字添加到行的前 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 test
,perl
也將是最佳選擇:
perl -pi -e 's{This is a test\K}{$n++ < 3 ? "." : ""}ge' your-file
^不使用-i inplace
as嘗試先從目前工作目錄gawk
載入inplace
擴充功能(asinplace
或),有人可能已經在其中植入了惡意軟體。隨系統提供的擴展inplace.awk
的路徑可能會有所不同,請參閱輸出inplace
gawk
gawk '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