在sed中使用管道(或)

时间:2015-05-12 15:12:57

标签: regex linux sed makefile

来自包含

之类的变量$(JS_SOURCES)
"    thing.js myapp.mod1.js otherthing.js myapp.mod1.submod.js myapp.othermodule.js   "

make写入包含mod1,othermodule

的文件

它适用于此代码:

./build/modules.txt: $(JS_SOURCES)
    @echo "$(JS_SOURCES)" | sed -r -e 's/\s\S*myapp\.(\w+)\.js\b/ \1/g' -e 's/\S*\.\S*//g' -e 's/^\s+//' -e 's/\s+$$//' -e 's/\b\s+\b/,/g' > $@

我的问题是为什么我不能替换3个表达式

-e 's/\S*\.\S*//g' -e 's/^\s+//' -e 's/\s+$$//'

一个使用管道

-e 's/\S*\.\S*|^\s+|\s+$$//g'

较短的sed命令不会修剪字符串(两个表达式的目的)。

为什么不起作用?如何解决这个问题(当然不使用几个表达式)?

操作系统是Ubuntu 14.10。我对使用替代工具不感兴趣,但在如何中使用带有从makefile调用的sed的正则表达式中的管道。

2 个答案:

答案 0 :(得分:1)

Arkanosis是正确的:组合是错误的,在shell中也是错误的。它与make没有任何关系:

echo "    thing.js myapp.mod1.js otherthing.js myapp.mod1.submod.js myapp.othermodule.js   " \
    | sed -r -e 's/\s\S*myapp\.(\w+)\.js\b/ \1/g' \
             -e 's/\S*\.\S*//g' -e 's/^\s+//' -e 's/\s+$//' -e 's/\b\s+\b/,/g' \
          > /tmp/x.out \
    && echo "|$(cat /tmp/x.out)|"

所示:

|mod1,othermodule|

现在使用一体化方法:

echo "    thing.js myapp.mod1.js otherthing.js myapp.mod1.submod.js myapp.othermodule.js   " \
    | sed -r -e 's/\s\S*myapp\.(\w+)\.js\b/ \1/g' \
             -e 's/\S*\.\S*|^\s+|\s+$//g' -e 's/\b\s+\b/,/g' \
          > /tmp/x.out \
    && echo "|$(cat /tmp/x.out)|"

你得到:

| mod1,othermodule|

你必须在shell命令中做一些让你觉得它有用的事情。

它不起作用的原因是在原始版本中,-e中的每个表达式一个接一个地应用于字符串,因此全部生效。

在新版本中,将所有三个条件压缩为单个表达式,它只应用一次,并且只选择三个备选项中的一个(这就是管道的内容)符号表示正则表达式。

答案 1 :(得分:0)

@Arkanosis所证明的问题不在于使用make。

正如@MadScientist暗示的那样,正则表达式是错误的。

问题是,当字符串 通过s/\S*\.\S*|^\s+|\s+$$//g进行修剪时,表达式不会删除最初不在字符串末尾的空格(即单词之间的空格)并结束在字符串的末尾。

一旦清楚,解决方案很明显:在第三种情况下删除这些空格:s/\s*\S*\.\S*\s*|^\s+|\s+$$//g

除此之外不会留下任何空间用于下一次替换,所以我所拥有的最简单的解决方案是

-e 's/\S*\.\S*//g' -e 's/^\s+|\s+$$//g'