首页 > 解决方案 > sed 未按预期打印匹配组

问题描述

我期望的是只有letter会出现在我的第一组中,但我仍然会得到digit

这是我的 sed:
echo "AAA-TTS-MAN-M4A ,abc,blurblur" |sed -r 's/(\(-?[A-Z]+)\)\(,[a-z]{2,}\)\(,.*\)/\1\/2\/3/p'

我希望这只会发泄: AAA-TTS-MAN ,abc,blurblur

但相反,它也显示有数字的 M4A。

请帮助我理解我错在哪里。谢谢!

标签: sed

解决方案


这可能对您有用(GNU sed):

sed -En 's/^([A-Z]+\b(-[A-Z]+\b)*)[^,]*((,[a-z]+)*).*/\1\3/p' file

使用该选项可减少,和运算符-E的反斜杠数量。使用该选项来防止隐式打印。()+-n

  • 正则表达式通过使用运算符锚定到行^首。
  • 第一个反向引用应该返回第一个字段减去任何不需要的连字符。
    • [A-Z]+\b匹配一个或多个以单词边界结尾的大写字母。
    • (-[A-Z]+\b)*匹配零个或多个连字符的单词。
  • [^,]*匹配零个或多个非逗号字符(这些字符将丢失)。
  • (,[a-z]+)*匹配零个或多个以逗号开头的小写字符单词。
  • .*将任何剩余的字符匹配到行尾(再次丢失)。

NB 分组和反向引用使用括号作为分隔符,因此反向引用 2 和 4 分别被反向引用 1 和 3 吞没。

根据OP的评论:

sed -E 's/^([A-Z]*([0-9][A-Z0-9]*)+-)+//;:a;/^[^,]*[0-9]/s/-[A-Z]*([0-9][A-Z0-9]*)+\b//;ta' file

第一个替换删除了第一个字段开头的所有单词。第二个替换在循环内(因为每个替换必须引用行首)并以正则表达式为前缀,以保证替换只影响第一个字段。


推荐阅读