“sed”命令删除与第一个单词

时间:2018-05-18 17:21:11

标签: regex bash shell sed

我在这里找到了一个问题的答案:"sed" command to remove a line that match an exact string on first word

...但只是部分原因,因为该解决方案仅在我查询的答案与答案人员完全一致时才有效。

他们回答说:

 sed -i "/^maria\b/Id" file.txt

...只删除以“maria”开头的一行,而不是maria,如果它不是第一个单词的话。

我想在一个文件中删除一个特定的URL,例如:“cnn.com” - 但是,我还有一堆本地主机地址,0.0.0.0,并且两者都有一些前面有一个空格。我也不想删除像ads.cnn.com这样的子域名,这样代码“应该”可以工作,但是当我使用-e选项输入更多命令时,代码“不应该”。我的下面的代码似乎清理得很好,除了我不能让它击败cnn.com!我的文件名为raw.txt

 sed -r -e 's/^127.0.0.1//' -e 's/^ 127.0.0.1//' -e 's/^0.0.0.0//' -e 's/^ 0.0.0.0//' -e '/#/d' -e '/^cnn.com\b/d' -e '/::/d' raw.txt | sort | tr -d "[:blank:]" | awk '!seen[$0]++' | grep cnn.com

当我grep for cnn.com时,我看到所有的cnn包括我不想要的那个实际上是“cnn.com”。

 ads.cnn.com
 cl.cnn.com
 cnn.com <-- the one I don't want
 cnn.dyn.cnn.com
 customad.cnn.com
 gdyn.cnn.com
 jfcnn.com
 kermit.macnn.com
 metrics.cnn.com
 projectcnn.com
 smetrics.cnn.com
 tiads.sportsillustrated.cnn.com
 trumpincnn.com
 victory.cnn.com
 xcnn.com

如果我只是使用cnn.com中的一段代码,它似乎有效。

 sed -r '/^cnn.com\b/d' raw.txt | grep cnn.com
 * I'm not using the "-e" option

结果:

 ads.cnn.com
 cl.cnn.com
 cnn.dyn.cnn.com
 customad.cnn.com
 gdyn.cnn.com
 jfcnn.com
 kermit.macnn.com
 metrics.cnn.com
 projectcnn.com
 smetrics.cnn.com
 tiads.sportsillustrated.cnn.com
 trumpincnn.com
 victory.cnn.com
 xcnn.com

当我将命令与“-e”选项一起使用时,我所做的任何事情似乎都无效。我需要一些帮助才能让我的多选项命令与SED一起踢。

有什么建议吗?

Ubuntu 12 LTS&amp; 16 LTS。
sed(GNU sed)4.2.2

2 个答案:

答案 0 :(得分:0)

.是正则表达式中的元字符,表示&#34;匹配任何一个字符&#34;。因此,您不小心创建了一个也会捕获cnnPcomcnn comcnn\com的正则表达式。虽然它可能适合您的需求,但最好更明确一点:

  sed -r '/^cnn\.com\b/d' raw.txt 

这里的区别是\期之前的.反斜杠。这逃脱了时期元素,因此它被视为一个字面时期。

对于以空格开头的行,您可以在单个正则表达式中捕获这些行(再次转义句点元字符):

  sed -r '/(^[ ]*|^)127\.0\.0\.1\b/d' raw.txt

(^[ ]*|^)表示以任意数量的重复空格^[ ]*|开头的行以^开头,然后是127.0.0.1的匹配}。

然后,为了将这些字符串串在一起,您可以使用parantheses中的| OR运算符来捕获所有匹配项:

  sed -r '/(^[ ]*|^)(127\.0\.0\.1|cnn\.com|0\.0\.0\.0)\b/d' raw.txt

或者,您可以使用;分号来分隔不同的正则表达式:

  sed -r '/(^[ ]*|^)127\.0\.0\.1\b/d; /(^[ ]*|^)cnn\.com\b/d; /(^[ ]*|^)0\.0\.0\.0\b/d;' raw.txt

答案 1 :(得分:0)

sed不理解字符串上的匹配,只理解正则表达式,并且尝试让sed像它一样行动是非常困难的,请参阅Is it possible to escape regex metacharacters reliably with sed。删除第一个以空格分隔的单词为“foo”的行只是:

awk '$1 != "foo"' file

删除以“foo”或“bar”开头的行只是:

awk '($1 != "foo") && ($1 != "bar")' file

如果您只有几个单词,那么方法是将它们全部列出并创建一个由它们索引的哈希表,然后测试您的行的第一个单词是哈希表的索引:

awk 'BEGIN{split("foo bar other word",badWords)} !($1 in badWords)' file

如果那不是您想要的,那么请编辑您的问题以阐明您的要求,并提供简洁,可测试的样本输入和 预期输出。