我需要在shell脚本中提取字符串的一部分。原始字符串非常复杂,所以我真的需要一个正则表达式来选择原始字符串的正确部分 - 只是删除前缀和后缀将不起作用。此外,正则表达式需要检查我想要提取的字符串的上下文,所以我例如需要使用正则表达式a\([^b]*\)b
从123
中提取12a123b23
。
shell脚本需要是可移植的,因此我无法使用Bash结构[[
和BASH_REMATCH
。
我希望脚本是健壮的,所以当正则表达式不匹配时,脚本应该注意到这一点,例如通过要使用的命令的非零退出代码。
这样做的好方法是什么?
我尝试了各种工具,但没有一个能完全解决问题:
expr match "$original" ".*$regex.*"
除错误情况外有效。使用此命令,我不知道如何检测正则表达式是否不匹配。此外,expr似乎采取提取的字符串来确定其退出代码 - 所以当我碰巧提取00
时,expr的退出代码为1.所以我需要通常忽略退出代码{{1} }
expr match "$original" ".*$regex.*" || true
也有效。为了处理这种情况,我需要测试我是否找回原来的字符串,这也非常不优雅。
那么,有没有更好的方法呢?
答案 0 :(得分:3)
您可以使用-n
的{{1}}选项来抑制所有输入行的输出,并将sed
选项添加到substitute命令中,如下所示:
p
如果正则表达式匹配,则匹配的组将像以前一样打印。但是现在如果正则表达式不匹配,则不会打印任何内容,您只需要测试空字符串。
答案 1 :(得分:2)
grep -o
唯一可能的问题是可移植性,否则它满足所有要求:
➜ echo "hello and other things" | grep -o hello
hello
➜ echo $?
0
➜ echo "hello and other things" | grep -o nothello
➜ echo $?
1
最好的事情之一是,因为它是grep你可以选择你想要的正则表达式,无论是BRE,ERE还是Perl。
答案 2 :(得分:0)
如果egrep可用(几乎所有时间)
egrep 'YourPattern' YourFile
或
egrep "${YourPattern}" YourFile
如果只有grep可用
grep -e 'YourPattern' YourFile
您使用经典[ $? -eq 0 ]
检查命令的状态(还考虑了错误的YourFile访问权限)
对于内容本身,用sed或awk提取(用于可移植性问题)(在失败测试之后)
Content="$( sed -n -e "s/.*\(${YourPattern}\).*/\1/p;q" )"