如何在/bin/sh脚本中使用正则表达式获取字符串的一部分



我需要在shell脚本中提取字符串的一部分。原始字符串非常复杂,所以我真的需要一个正则表达式来选择原始字符串的正确部分——仅仅删除前缀和后缀是行不通的。此外,正则表达式需要检查我想要提取的字符串的上下文,所以我需要一个正则表达式a([^b]*)b12a123b23中提取123

shell脚本需要是可移植的,所以我不能使用Bash结构[[BASH_REMATCH

我希望脚本是健壮的,所以当正则表达式不匹配时,脚本应该注意到这一点,例如通过要使用的命令的非零退出代码。

做这件事的好方法是什么?


我尝试了各种工具,但没有一个能完全解决问题:

  • expr match "$original" ".*$regex.*"除错误情况外有效。使用这个命令,我不知道如何检测正则表达式是否不匹配。此外,expr似乎使用提取的字符串来确定其退出代码—因此,当我碰巧提取00时,expr的退出代码为1。所以我通常需要忽略expr match "$original" ".*$regex.*" || true

  • 的退出代码除错误情况外,
  • echo "$original" | sed "s/.*$regex.*/\1/"也有效。为了处理这种情况,我需要测试是否返回了原始字符串,这也相当不美观。

那么,没有更好的方法来做到这一点吗?

您可以使用sed-n选项来抑制所有输入行的输出,并将p选项添加到替换命令中,如下所示:

echo "$original" | sed -n -e "s/.*$regex.*/1/p"

如果正则表达式匹配,则与前面一样打印匹配的组。但是现在,如果正则表达式不匹配,则不会打印任何内容,您只需要测试空字符串。

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。

如果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" )"

最新更新