删除特殊字符之间的单词

删除特殊字符之间的单词

如何使用 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;
' 

相关内容