嘗試使用 sed 正規表示式刪除單字結尾字符

嘗試使用 sed 正規表示式刪除單字結尾字符

我是正規表示式和 sed 的新手,並且正在嘗試創建一個我認為簡單的正則表達式:我想刪除單字結尾的字母(如果它是“o”)。

  • 輸入字串:你好你好
  • 預期輸出:地獄地獄

好消息:當“o”位於字串末尾時,我可以將其刪除:

$ echo 'Hello Hello' |sed 's/\(.*\)o/\1/g'
Hello Hell
$ echo 'Hello Hello' |sed 's/\(.*\)o$/\1/g'
Hello Hell

壞消息:我無法將其從字串前面的單字中刪除。我已經嘗試過使用我能想到的所有錨符號。結果是詞尾的「o」都沒有刪除:

$ echo 'Hello Hello' |sed 's/\(.*\)o\b/\1/g'
Hello Hello
$ echo 'Hello Hello' |sed 's/\(.*\)o\>/\1/g'
Hello Hello
$ echo 'Hello Hello' |sed 's/\(.*\)o\W/\1/g'
Hello Hello
$ echo 'Hello Hello' |sed 's/\(.*\)o\s/\1/g'
Hello Hello

你能告訴我我做錯了什麼來幫助我恢復理智嗎?

更新:我的明顯印像是我的機器產生的結果與其他人的結果不同。我正在 Macbook 上使用終端機視窗。如果有人能解釋這一點,請告訴我。

答案1

echo 'Hello Hello' | sed 's/o$//'

對我來說似乎比你的更有用

echo 'Hello Hello' | sed 's/\(.*\)o$/\1/g'

你的問題是說輸出

echo 'Hello Hello' | sed 's/\(.*\)o\b/\1/g'

Hello Hello,但對我來說卻是Hello Hell。您可以將其更正為

echo 'Hello Hello' | sed 's/\([^o]*\)o\b/\1/g'

echo 'Hello Hello' | sed 's/o\b//g'

對我來說似乎更好。

答案2

刪除o單字末尾的 the 就是刪除單字字元和非單字字元(或 EOL)之間的 ao,因此:

sed -r 's/(\w)o(\W|$)/\1\2/g'

答案3

我想知道是否space不是你的單字分隔符號。嘗試如下操作:

$ echo hello hello | sed -e 's/o / /g;s/o$//'
hell hell

此範例的問題在於,您還必須對.and,以及任何其他單字分隔符號執行相同的操作。匹配o後跟另一個特定字符,如[]like o[ \.,]。由於某種原因,這不適用於 EOL $,因此請使用 . 新增另一個搜尋字串;。例子:

$ echo hello hello, hello. toot hello | sed -e 's/o\([ \.,]\)/\1/g;s/o$//'
hell hell, hell. toot hell
$ echo $SHELL
/bin/bash
$ sed --version
sed (GNU sed) 4.4
$ set | grep IFS
IFS=$' \t\n'

答案4

我已經嘗試過使用我能想到的所有錨符號。

這不是錨點,而是您與星號進行貪婪匹配的事實。表達式\(.*\)o匹配盡可能長的字串,所以它會吃掉所有東西最後的 o。它o也可能與先前的匹配。

但是,捕獲一些東西然後將其返回是沒有用的,你可以完全刪除\(.*\)\1

因此,這些將(至少在 GNU sed 中)刪除o單字末尾的 :

sed 's/o\>//g' 
sed 's/o\b//g' 

當然,這僅在字串末尾:

sed 's/o$//g' 

這將刪除o, 以及以下非單字字元(例如 後面的空格Hello):

sed 's/o\W//g' 

如果您sed不支持\</\>\b,您將不得不做其他事情。這將匹配o後跟非字母數字字元或行尾:

$ echo "jello, jello" | sed -E -e 's/o([^[:alnum:]]|$)/\1/g'
jell, jell

sed例如,這適用於OS X/macOS 隨附的作業系統。


Perl 正規表示式支援添加問號*+使其成為非貪婪的。然後他們會匹配最短可能的字串:

echo "jello, jello" | perl -pe 's/(.*?)o/$1/g'
jell, jell

相關內容