使用sed删除匹配的模式

时间:2015-07-21 14:31:32

标签: sed

我有一个我需要清理的.txt文件,一组具有一致模式的字符串,以及一组匹配的字符串。我的意思如下:

我想删除括号中包含的所有内容,后跟冒号,例如[example]:

然后我还要删除该单词的所有实例,例如

要完成第一部分,我使用以下内容:

sed -i new 's/\[.*]://g' rp.txt

我需要添加什么来实现第二部分,这也会删除任何匹配*?

的字符串

示例输入:

[John]: Hello Mary.
[Mary]: Hello John.

期望的输出:

Hello .
Hello .

在Mac中使用终端。

1 个答案:

答案 0 :(得分:2)

修订问题的答案

如评论中所述,修订后的方案需要对数据进行两次传递。第一遍确定需要编辑的内容。第二遍应用编辑。该解决方案包括sort -u以消除方括号中给定单词的重复条目,因此第一个' pass实际上涉及两个sed脚本。

脚本

sed -e '/\[/!d' \
    -e 's/]:[^][]*$/]:/' \
    -e 's/^[^[]*//' \
    -e 's/[^][]*\(\[[^]]*]\):/\1/g' \
    -e 's/\[//g' \
    -e 's/]/\n/g' data |
sort -u |
sed -e '/^[    ]*$/d' \
    -e h \
    -e 's%.*%s/\\[&]://%p' \
    -e g \
    -e 's%.*%s/\\<&\\>//%' |
sed -f - data

请注意,这会将sed脚本作为标准输入提供-f -选项。并非sed的所有版本都必须支持此功能。 如果您没有,则必须在临时文件中捕获生成的sed脚本,将该文件提供给sed,然后将其删除。或者使用process substitution

生成的脚本

s/\[John]://
s/\<John\>//
s/\[Mary]://
s/\<Mary\>//
s/\[Name]://
s/\<Name\>//
s/\[like]://
s/\<like\>//
s/\[one]://
s/\<one\>//
s/\[something]://
s/\<something\>//

请注意,这是使用GNU sed,它支持\b…\b\<…\>来围绕单词(至少使用-r; \<…\>表示法有效没有-r选项)。即使在sed选项下,Mac OS X(BSD)-E也不支持。

样本数据

[John]: Hello Mary.
[Mary]: Hello John.
[John]: Frank Johnson has a Name that is familiar.
[Mary]: A line [like]: this [one]: or [something]: similar should
be munged too.
[John]: A longer conversation with Mary that extends over several
lines which means that not all lines start with [Name]: but it
may actually be that when it occurs, [Name]: only actually
appears at the start of a line.
[Mary]: But it doesn't matter; we don't like this one, but
something similar should be OK, and should likely pacify the
Nameless ones, or someone acting all lonely on their behalf.

示例输出

 Hello .
 Hello .
 Frank Johnson has a  that is familiar.
 A line  this  or  similar should
be munged too.
 A longer conversation with  that extends over several
lines which means that not all lines start with  but it
may actually be that when it occurs,  only actually
appears at the start of a line.
 But it doesn't matter; we don't  this , but
 similar should be OK, and should likely pacify the
Nameless ones, or someone acting all lonely on their behalf.

添加代码以删除前导和尾随空白并通过单个替换多个空白将很容易。稍微复杂的操作可以在标点符号之前删除空格,例如逗号或句号(句点)。

原始答案

  

我想删除括号中包含的所有内容,后跟冒号,例如[example]:

     

然后我还要删除单词example

的所有实例

删除方括号中包含的后跟冒号的内容很棘手,因为空方括号是一个元字符。输出应该包含空[]:吗?如果逐字阅读,问题是什么,但你可能不想要它。所以,你需要一个:

-e 's/\[[^]]*]://g'        # Remove the square brackets and colon too
-e 's/\[[^]]*]:/[]:/g'     # Retain the square brackets and colon

诀窍在于,在字符类[…]中,]必须是字符类开头的[[^之后的第一个字符。在正则表达式中,]不是元字符;只有在[后才能成为元字符。

请注意,这两者仅匹配第一个]。如果您使用.*代替[^]]*,则可以消除太多:

a line [like]: this [one]: or [something]: similar.

然后,除非您想要保持examplesunexampled不变,否则其他操作很简单:

-e 's/example//g'      # Remove the string example when it appears

如果您想处理字边界,则需要阅读机器的sed手册。 sed的不同变体具有用于标记单词边界的不同选项;有些人没有任何选择权。当他们支持它时,\<example\>是一种表示法; \bexample\b是另一个。