Linux命令sed中的正则表达式

时间:2012-02-22 03:45:17

标签: regex linux shell sed

我有一个shell变量:

all_apk_file="a 1 2.apk x.apk y m.apk"

我想使用以下命令将a 1 2.apk替换为TEST

echo $all_apk_file | sed 's/(.*apk ){1}/TEST/g'

.*apk表示以apk结尾,{1}表示只匹配一次,但它不起作用;我只将原始变量作为输出:a 1 2.apk x.apk y m.apk

谁能告诉我为什么?

3 个答案:

答案 0 :(得分:2)

首先,要启用sed中您熟悉的正则表达式,您需要使用-r开关(sed -r ...):

echo $all_apk_file | sed -r 's/(.*apk ){1}/TEST/g'
# returns TESTy m.apk

查看它返回的内容:TESTy m.apk。这是因为.* 贪婪,所以它与尽可能匹配。也就是说,.*匹配a 1 2.apk x,并且您说要替换.*apka 1 2.apk x.apk替换为'TEST',结果为TESTy m.apk(请注意正则表达式中“.apk”之后的以下空格,这就是为什么匹配不会一直延伸到最后一个'.apk'的原因,后面没有空格。)

通常可以将.*更改为.*?以使其非贪婪,但sed不支持此行为。

所以,要修复它,你只需要让你的正则表达式更具限制性。

很难说出你想做什么 - 删除前三个单词,其中第三个单词以'.apk'结尾,并替换为'TEST'?在这种情况下,可以使用正则表达式:

[a-z0-9]+ +[a-z0-9]+ +[a-z0-9]+\.apk

与'i'开关组合(不区分大小写)。

你必须给出决定删除内容的逻辑(前三个单词,任意数量的单词直到第一个'.apk'单词等),以便我们帮助你进一步使用正则表达式。

其次,您已将'g'开关置于正则表达式中。这意味着所有匹配模式将被替换,您似乎只希望第一个被替换。所以删除'g'开关。

最后,所有这些组合:

echo $all_apk_file | sed -r 's/[a-z0-9]+ +[a-z0-9]+ +[a-z0-9]+\.apk/TEST/i'
# TEST x.apk y m.apk

答案 1 :(得分:1)

这可能对您有用:

echo "$all_apk_file" | sed 's/apk/\n/;s/.*\n/TEST/'
TEST x.apk y m.apk

至于为什么你的正则表达式不起作用,请参阅@ mathematicalcsoffee和@Jonathan Leffler的优秀解释。

s/apk/\n/s/apk/\n/1同义,这意味着将apk的第一次出现替换为\n。由于sed使用\n作为记录分隔符,我们知道它不会出现在传递给sed命令的任何初始字符串中。有了这两个事实,我们可以分裂。

N.B。如果您想要替换第二个apk,那么s/apk/\n/2将适合该帐单。当然,对于apk的最后一次出现,然后.*apk开始发挥作用。

答案 2 :(得分:0)

问题的一部分是,在常规sed中,(){}是模式中的普通字符,直到使用反斜杠进行转义。由于变量值中没有括号,因此正则表达式永远不会匹配。使用GNU sed,您还可以使用-r标志启用扩展正则表达式。如果您解决了这个问题,那么您将遇到.*贪婪的问题,g修饰符实际上不会改变任何内容:

$ echo $all_apk_file | sed 's/\(.*apk \)\{1\}/TEST/g'
TESTy m.apk
$ echo $all_apk_file | sed -r 's/(.*apk ){1}/TEST/g'
TESTy m.apk
$ echo $all_apk_file | sed -r 's/(.*apk ){1}/TEST/'
TESTy m.apk
$

它只会在那里停止,因为在变量的回显值中m.apk之后没有空格。

现在的问题是:你想要替换的是什么?这听起来像'一切都包含在一个单词末尾的apk的第一次出现。这可能最容易通过Perl正则表达式中的尾随上下文或非贪婪匹配来完成。如果可以选择切换到Perl,请执行此操作。如果不是,那么在正常的sed正则表达式中这不是微不足道的。

$ echo $all_apk_file | sed 's/^[^.]* [^.][^.]*\.apk /TEST /'
TEST x.apk y m.apk
$

这会查找没有点的任何内容,后面跟一个空格,然后再没有点,.apk;这意味着允许的第一个点是2.apk中的点。它适用于样本数据;如果变量包含:

,它将无法工作
all_apk_file="a 1.2 2.apk m.apk y.apk 37"

您需要对其进行调整以满足您的要求。