无法从文件名中提取模式

时间:2013-05-21 07:24:34

标签: unix sed

从以下sed命令获取错误:

echo 20130521_OnePKI_p107336_APP.pfx | sed -e 's/_\([pP][0-9]+\)_/\1/'

不是返回p107336,而是返回完整的filenam 20130521_OnePKI_p107336_APP.pfx

为什么会发生这种情况,以及如何将输出限制为我想要的模式?

4 个答案:

答案 0 :(得分:1)

捕获应该是转义括号,您可以使用不区分大小写的匹配i,同时,您正在使用捕获的部分替换捕获部分,因此不会进行任何更改。这个匹配整行,并用捕获的模式替换它:

sed -e 's/.*_\([pP][0-9][0-9]*\)_.*/\1/'

答案 1 :(得分:1)

更简单的方法可能是使用grep:

echo 20130521_OnePKI_p107336_APP.pfx | egrep -o "[pP][0-9]+"

“-o”告诉grep只打印输入的匹配部分。

答案 2 :(得分:1)

正则表达式[pP][0-9]+原则上匹配任何以pP开头,后跟一个或多个数字的子字符串。字符串"20130521_OnePKI_p107336_APP.pfx"有一个匹配该模式的子字符串,因此整个字符串与正则表达式匹配。

当在左边的整个正则表达式中使用括号进行分组并在右侧引用它时,就像在's/([pP][0-9]+)/\1/'中一样,你基本上是在说“用自己替换匹配”,这自然会导致与首先相同的字符串。

这里你需要的是从开头匹配整个字符串,然后将该字符串的一部分分组,如前所述。然后你可以参考右侧的那个部分从较大的字符串中提取它。

在shell中工作时,您需要适当地转义表达式。

答案 3 :(得分:0)

你必须逃避parens和+。同时匹配所有字符串并将其全部替换为您希望的部分(.*之前和结束字符串):

... | sed -e 's/^.*\([pP][0-9]\+\).*$/\1/'