bash regexp (sed) 抑制“不匹配”输出

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6011661/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 00:00:29  来源:igfitidea点击:

regexp (sed) suppress "no match" output

regexbashshellsed

提问by yPhil

I'm stuck on that and can't wrap my head around it: How can I tell sed to return the value found, and otherwise shut up?

我被困在这个问题上并且无法解决它:我怎么能告诉 sed 返回找到的值,否则闭嘴

It's really beyond me: Why would sed return the whole string if he found nothing? Do I have to run anothertest on the returned string to verify it? I tried using "-n" from the (very short) man page but it effectively suppresses all output, including matched strings.

实在是想不通了:sed 一无所获,为什么还要返回整个字符串呢?我是否必须对返回的字符串运行另一个测试来验证它?我尝试使用(非常短的)手册页中的“-n”,但它有效地抑制了所有输出,包括匹配的字符串。

This is what I have now :

这就是我现在所拥有的:

echo plop-02-plop | sed -e 's/^.*\(.\)\([0-9][0-9]\).*$//'

which returns 02(and that is fine and dandy, thank you very much), but:

返回 02(这很好,很花哨,非常感谢),但是:

echo plop-02plop | sed -e 's/^.*\(.\)\([0-9][0-9]\).*$//'

returns plop-02plop(when it should return this = "" nothing! Dang, you found nothing so be quiet! For crying out loud !!)

返回 plop-02plop(什么时候应该返回 this = ""什么都没有!Dang,你什么都没发现,所以安静点!大声哭!)

I tried checking for a return value, but this failed too ! Gasp !!

我尝试检查返回值,但这也失败了!喘气!!

$ echo plop-02-plop | sed -e 's/^.*\(.\)\([0-9][0-9]\).*$//' ; echo $?
02
0
$ echo plop-02plop | sed -e 's/^.*\(.\)\([0-9][0-9]\).*$//' ; echo $?
plop-02plop
0
$

This last one I cannot even believe. Is sedreally the tool I should be using? I want to extract a needle from a haystack, and I want a needle or nothing..?

这最后一个我什至无法相信。是sed真的,我应该使用的工具?我想从大海捞针,我想要一根针还是什么都不想要..?

回答by przemoc

sed by default prints all lines.

sed 默认打印所有行。

What you want to do is

你想做的是

/patt/!d;s//repl/

IOW delete lines not matching your pattern, and if they match, extract particular element from it, giving capturing group number for instance. In your case it will be:

IOW 删除与您的模式不匹配的行,如果它们匹配,则从中提取特定元素,例如提供捕获组编号。在您的情况下,它将是:

sed -e '/^.*\(.\)\([0-9][0-9]\).*$/!d;s///'

You can also use -noption to suppress echoing all lines. Then line is printed only when you explicitly state it. In practice scripts using -nare usually longer and more cumbersome to maintain. Here it will be:

您还可以使用-n选项来抑制回显所有行。然后仅当您明确说明时才打印 line。在实践中,使用-n的脚本通常更长,维护起来也更麻烦。这将是:

sed -ne 's/^.*\(.\)\([0-9][0-9]\).*$//p'

There is also grep, but your example shows, why sed is sometimes better.

还有 grep,但您的示例显示了为什么 sed 有时更好。

回答by sehe

Perhaps you can use egrep -o?

也许你可以使用egrep -o

input.txt:

输入.txt:

blooody
aaaa
bbbb
odor
qqqq

E.g.

例如

sehe@meerkat:/tmp$ egrep -o o+ input.txt 
ooo
o
o
sehe@meerkat:/tmp$ egrep -no o+ input.txt 
1:ooo
4:o
4:o

Of course egrepwill have slightly different (better?) regex syntax for advanced constructs (back-references, non-greedy operators). I'll let you do the translation, if you like the approach.

当然egrep,高级构造(反向引用、非贪婪运算符)的正则表达式语法会略有不同(更好?)。如果你喜欢这种方法,我会让你做翻译。