Text-Processing

使用 ‘sed’ 替換任何單詞,而不是字元

  • November 4, 2022

我知道如何使用sed語法[^xxxx]排除字元,但是如何排除單詞?例如我的變數:

var="
Now is the time
for all good men 
to come 
to the aid  
of the party" 

現在:

echo $var | sed ...

…我想結束:

REPLACED time
for all good men 
to come 
REPLACED aid  
REPLACED party 

…這應該很簡單,但我不知道該怎麼做。

echo $var | sed -r 's/^[^the]*the/REPLACED/'

… 有點接近,但是t h e作為單個字元匹配,而不是作為 word 匹配the

如果有解決方案,我可以將所有內容替換為多次出現中的第一次,甚至可以替換為特定出現,那會更好。

s/.*the/REPLACED/替換最右邊的所有內容,the因為那.*是貪婪的並且希望盡可能多地匹配。

.*是 0 個或多個 ( *) 字元 ( .)*盡可能多,*並且會愉快地吞噬所有出現的the不包括最後一個需要由正the則表達式的以下部分匹配的字元。

大約 30 年前,這被perl5 修復了,它引入了一個非貪婪版本*: *?,它匹配前面的 0 個或更多,但盡可能少

printf '%s\n' "$var" | perl -pe 's/.*?the/REPLACED/'

很少sed有添加對這些新perl運算符的支持。我只知道兩個實現(ssedwith-R和 ast-open 的 with -P)。

在其他sed實現中,當要替換的內容是單個字元(如x)時,您可以使用除 () 之外s/[^x]*x/REPLACE/的 0 個或多個 ( )*字元,盡可能多地表示,並且因為我們排除了 ,所以它將在第一次出現之前儲存。x``[^x]``x``x

*您不能將其用於超過一個字元的字元串,因為只要不包含 “the” ,*就不能說盡可能多的 0 個或多個字元。所以你需要一種不同的方法。

s/the/REPLACEMENT/替換 的第一次出現the,因此標準sed中替換所有字元串直到第一次出現的所有內容的常用方法是用換行符替換它(否則該字元保證不會出現在模式空間中),然後替換該換行符之前的所有內容:

sed 's/the/\
/;s/.*\n//'

您可以按如下方式實現,假設the線上上最多有一個 的實例:

sed -E 's/.*\Wthe(\W.*)/REPLACED\1/'

the這將用您的替換文本替換最後一次出現的所有內容(請記住,RegExes 是貪婪的) 。

  • 它通過將最後一次出現之後的所有內容儲存在擷取組中the,並由非單詞字元包圍(以防止部分單詞匹配,例如theoretical)來實現,包括以 , 結尾的非單詞字元。the``( ... )
  • 然後它將用替換文本替換該行,然後是擷取組的內容(稱為,\1因為它是搜尋模式中的第一個此類組)。這種有些複雜的方法是必要的,以便終止的字元the也被轉移到替換文本中。

如果您想替換所有內容直到第一次出現,您可能不得不求助於awk

awk '(i=match($0,/\Wthe\W/)){print "REPLACED" substr($0,i+4);next} 1'

這將檢查the被非單詞字元包圍的字元串是否出現在行上,並將位置儲存在變數i中。

  • 如果i為非零,它將列印替換文本和目前輸入行的子字元串,從出現後開始the,否則跳過執行到下一行。
  • 如果i為零,它只是按原樣列印目前行。

引用自:https://unix.stackexchange.com/questions/723659