如何使用 sed 删除两个特殊字符之间的所有单词?请注意,原始行也必须包含在结果中。
当前代码:
echo 'a "removeme" b +removeme+ c *removeme#d+removeme~ .123' | sed -r '/\W/ p; s/\W[^\W]*\W//g'
结果:
a "removeme" b +removeme+ c *removeme#d+removeme~ .123
a123
预期结果:
a "removeme" b +removeme+ c *removeme#d+removeme~ .123
a b c d .123
答案1
在您的特殊情况下,您可以:
- 将所有不需要的字符替换为单个已知字符(其中是该集合的一部分)
- 删除该替换字符的两个实例之间的所有字符串
echo 'a "removeme" b +removeme+ c *removeme#d+removeme~ .123' | sed -e '/\W/p; s/["+*#~]/#/g ; s/#[^#]\+#//g'
a "removeme" b +removeme+ c *removeme#d+removeme~ .123
a b c d .123
请注意,由于您想保留.
,因此不能使用“非单词”类,因为它们包含“.”。如果您想不惜一切代价避免给出明确的字符列表,您可以:
- 将点替换为您不太可能遇到的单词字符(thorn、斜线 O、重音 a/e/i/o/u 或希腊语/西里尔语)
- 使用 [:punct:] 应用上面的表达式
- 恢复点。
答案2
将所有点更改为换行符,保证不存在并确保非标点字符。那么这是两个标点符号之间的非贪婪匹配的简单问题:
$ echo 'a "removeme" b +removeme+ c *removeme#d+removeme~ .123' |
sed -e 'p
y/./\n/
s/[[:punct:]][^[:punct:]]*[[:punct:]]//g
y/\n/./
'
a "removeme" b +removeme+ c *removeme#d+removeme~ .123
a b c d .123
注意:这一切都在 Posix sed 内。
答案3
Perl 擅长处理此类情况。我们使用负向先行来创建一个不包括点的标点符号类别:
echo '......' |
perl -lpe '
print;
$p = qr/(?!\.)[[:punct:]]/;
s/$p.*?$p//g;
'