Sed

為什麼這個 sed 命令不替換倒數第三個“and”?

  • May 27, 2020

2020 年 5 月 26 日更新

看起來這是一個錯誤,所以我送出了一個錯誤。它的 ID 是#41558。


我只是在搞亂sed,我想出了這個練習:替換倒數第三次出現的“and”(這個詞,而不是子字元串),創建:

dog XYZ foo and bar and baz land good

我以為這行得通

echo 'dog and foo and bar and baz land good' |
   sed -E 's/(.*)\band\b((.*\band\b){2})/\1XYZ\2/'

但它實際上取代了倒數第二次出現的“and”。我能想到的唯一解釋是它包括“土地”作為其中之一\band\b,但不應該是這種情況,因為我包括了\b邊界這個詞?

這很難做到,因為sed不支持環視等(就像你可以在 PCRE 中做的那樣)。反轉字元串並從頭開始替換第三次出現的反轉單詞會更容易,然後再次反轉。

$ echo 'dog and foo and bar and baz land good' | rev | sed 's/\<dna\>/XXX/3' | rev
dog XXX foo and bar and baz land good

至於為什麼你的表達不起作用,這看起來像一個錯誤。反向引用\3似乎是 string baz land,好像\b之前and的 in.*\band\b從來沒有任何效果。

命令

sed -E 's/(.*)\<and\>((.*\<and\>){2})/\1XYZ\2/'

似乎在 OpenBSD 上使用其本機sed(使用\<and\>而不是\b)做正確的事情。

sed我還沒有找到針對 GNU或 GNU的現有錯誤報告glibc,儘管如果它至少glibc 錯誤 25322相關(因為,見下文),我不會感到驚訝。

您可以通過更詳細一些來解決它:

sed -E 's/(.*)\band\b(.*\band\b.*\band\b)/\1XYZ\2/'

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