在 sed 中使用管道(或)
Using a pipe (or) in sed
来自包含类似
的变量$(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/ /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 命令不 trim 字符串(两个表达式的目的)。
为什么不起作用?如何解决这个问题(当然不用诉诸多种表达方式)?
OS 是 Ubuntu 14.10。我对使用替代工具不感兴趣,但对 如何 在正则表达式中使用管道和从 makefile 调用的 sed 感兴趣。
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/ /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/ /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
中的每一个表达式都是一个接一个地应用到字符串上的,所以都生效了。
在新版本中,所有三个条件都浓缩为一个表达式,只应用一次,并且只会选择三个备选方案中的一个(这就是管道符号表示在正则表达式中)。
正如@Arkanosis 所证明的那样,问题不在于使用 make。
正如@MadScientist 所暗示的,正则表达式有问题。
问题是,虽然字符串 是 通过 s/\S*\.\S*|^\s+|\s+$$//g
修剪的,但 space 最初不在字符串的末尾(即 spaces between words) 不会被表达式删除并且 end 位于字符串的末尾。
一旦清楚,解决方案就很明显了:在第三种情况下删除那些space:s/\s*\S*\.\S*\s*|^\s+|\s+$$//g
除此之外不会让任何 space 留给下一次替换,所以我最好的简单解决方案是
-e 's/\S*\.\S*//g' -e 's/^\s+|\s+$$//g'
来自包含类似
的变量$(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/ /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 命令不 trim 字符串(两个表达式的目的)。
为什么不起作用?如何解决这个问题(当然不用诉诸多种表达方式)?
OS 是 Ubuntu 14.10。我对使用替代工具不感兴趣,但对 如何 在正则表达式中使用管道和从 makefile 调用的 sed 感兴趣。
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/ /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/ /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
中的每一个表达式都是一个接一个地应用到字符串上的,所以都生效了。
在新版本中,所有三个条件都浓缩为一个表达式,只应用一次,并且只会选择三个备选方案中的一个(这就是管道符号表示在正则表达式中)。
正如@Arkanosis 所证明的那样,问题不在于使用 make。
正如@MadScientist 所暗示的,正则表达式有问题。
问题是,虽然字符串 是 通过 s/\S*\.\S*|^\s+|\s+$$//g
修剪的,但 space 最初不在字符串的末尾(即 spaces between words) 不会被表达式删除并且 end 位于字符串的末尾。
一旦清楚,解决方案就很明显了:在第三种情况下删除那些space:s/\s*\S*\.\S*\s*|^\s+|\s+$$//g
除此之外不会让任何 space 留给下一次替换,所以我最好的简单解决方案是
-e 's/\S*\.\S*//g' -e 's/^\s+|\s+$$//g'