尝试使用 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

相关内容