我是正则表达式和 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