【问题标题】:regexp (sed) suppress "no match" output正则表达式(sed)抑制“不匹配”输出
【发布时间】:2011-08-26 01:57:59
【问题描述】:

我被困住了,无法理解它:我如何告诉 sed 返回找到的值,否则闭嘴

这真的超出了我的理解:如果 sed 一无所获,为什么会返回整个字符串?我是否必须对返回的字符串运行 another 测试来验证它?我尝试使用(非常短的)手册页中的“-n”,但它有效地抑制了所有输出,包括匹配的字符串。

这就是我现在拥有的:

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

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

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

返回 plop-02plop (当它应该返回 this = "" nothing!该死的,你什么也没找到,所以安静点! 大声哭泣!!)

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

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

最后一个我简直不敢相信。 sed 真的是我应该使用的工具吗?我想从大海捞针,我想要一根针或什么都没有..?

【问题讨论】:

  • 如您所见,sed 正在按照您的要求做;它是一个流编辑器,并将其输入打印到脚本修改的输出中。您的不匹配案例没有更改数据,因此回显的是您的输入 - 这是sed 的正确行为。抑制输出的答案是使用-n,然后在您想要打印某些内容时添加显式p

标签: regex bash shell sed


【解决方案1】:

sed 默认打印所有行。

你想做的是

/patt/!d;s//repl/

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

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

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

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

还有 grep,但你的例子表明,为什么 sed 有时更好。

【讨论】:

  • 我该死的,它有效。先生非常感谢您。 @sehe 谢谢,我会检查 grep。
  • 您可以将-n 版本缩短为:sed -ne 's/^.*\(.\)\([0-9][0-9]\)\1.*$/\2/p',它比没有-n 的版本短。
  • @Jonathan 你是完全正确的。在这种特殊情况下,-n 确实更短。我应该按照你从一开始就建议的方式写-n,但它不知何故让我忘记了。挺尴尬的。 ;)
  • @Jonathan @przemoc 又该怎么做才能得到相反的结果呢?那是返回没有匹配位的字符串?
  • @xaccrocheur 删除我的样板文件中的!(可能还有s/// 命令;取决于您是否要进一步修改它)。对于-n,它将是/patt/!p
【解决方案2】:

也许你可以使用egrep -o

输入.txt:

blooody
aaaa
bbbb
odor
qqqq

例如

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-11-01
    • 2018-12-30
    • 2014-09-06
    • 1970-01-01
    • 2014-09-03
    • 1970-01-01
    • 2018-05-25
    • 1970-01-01
    相关资源
    最近更新 更多