sed删除不包含特定字符串的行。

87

我对sed很陌生,我有一个以下问题。在这个例子中:

some text here
blah blah 123
another new line
some other text as well
another line

我想要删除除包含字符串'text'或者字符串'blah'的行以外的所有行,使得输出文件如下所示:

some text here
blah blah 123
some other text as well
有什么提示可以使用sed来完成这个任务吗?

5
答案必须使用sed吗?grep可以很容易地完成这个任务。 - Tim
1
https://askubuntu.com/a/847004/638128 - Stack Underflow
4个回答

124

这个可能适合你:

sed '/text\|blah/!d' file
some text here
blah blah 123
some other text as well

1
例如,我该如何指定文本或占位符只能出现在最后一列? - discipulus
3
如果你的意思是“在行末”,那么你应该使用 $'/text$\|blah$/!d' - Melebius
@potong 如果我将分隔符/替换为#,这种方法不起作用,有任何想法吗? - burglarhobbit
1
@burglarhobbit 我猜你指的是正则表达式分隔符/。在替换命令中,可以将其设置为任何分隔符,例如s#...#...#。但是,在用于匹配时,第一个分隔符必须加引号,例如将分隔符设置为#,使用\#match#d来删除匹配的行。 - potong

18

您想打印出与“text”或“blah”(或两者都匹配)相匹配的行,其中“and”和“or”的区别非常关键。

sed -n -e '/text/{p;n;}' -e '/blah/{p;n;}' your_data_file
-n的意思是默认不进行打印。第一个模式用于搜索“text”,如果匹配则打印并跳到下一行;第二个模式对“blah”执行同样的操作。如果没有使用“-n”,则包含“text和blah”的行将被打印两次。虽然我本可以使用 -e '/blah/p',但对称性更好,特别是在需要扩展匹配单词列表时。如果您的sed版本支持扩展正则表达式(例如GNU sed支持-r),则可以简化为:
sed -r -n -e '/text|blah/p' your_data_file

3
如果 sed 不支持 -r,那么它可能也不支持 {}。对于旧的 sed,这应该可以工作:sed '/text\|blah/!d' file。该命令的意思是从文件中删除所有不包含 "text" 或 "blah" 的行。 - glenn jackman
“{...}”命令组合是UNIX第7版版本的“sed”中的功能;我无法想象您会遇到不支持该功能的版本。 - Jonathan Leffler
@JamesThomasMoon1979 — 警惕一下包含“keep-this”、“keep-that”和“keep-those”的那一行。你的版本会打印三遍这一行,而我的只会打印一次。这取决于你所需要的输出。如果你想要将单行打印三次,那么你的解决方案是好的。如果不是,那么还有待改善。 - Jonathan Leffler
非常感谢您的反馈。在我的情况下,我遇到了这个错误场景:假设我想打印输入行aa b,以下命令只会打印第一行输入echo -e 'a\na b' | sed -n -e '/b/{p;n;}' -e '/a/{p;n;}'。但是如果我改变表达式的顺序,该命令将打印两行输入echo -e 'a\na b' | sed -n -e '/a/{p;n;}' -e '/b/{p;n;}' - JamesThomasMoon
@JonathanLeffler 是bug吗?嗯...这很可疑。我不是sed大师。我想知道是否可以找到旧的、鲜为人知但仍然活跃的Unix工具大师邮件列表。 - JamesThomasMoon
显示剩余3条评论

11

你可以简单地通过awk来完成它,

$ awk '/blah|text/' file
some text here
blah blah 123
some other text as well

0

你正在寻找 grep 吗? 以下是查找不同文本的示例。

cat yourfile.txt | grep "text\|blah"

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接