根据模式在 bash 脚本中提取字符串

And*_*rew 18 bash string shell-script

在 bash 中,假设我有一个字符串strname

strname="ph7go04325r"
Run Code Online (Sandbox Code Playgroud)

我想提取中第一个 "3"字符和最后一个 字符之间的"r"字符strname,将结果保存在一个字符串中strresult。在上面的例子中,结果strresult将是:

strresult="25"
Run Code Online (Sandbox Code Playgroud)

第一"3"字符是必然在串8位strname; 同样地,最后一个"r"必然在串位置11。因此,下面的两个串的strname应产生strresult="25"

strname="ph11go04325raa"
strname="325r"
strname="rgo04325raa"
Run Code Online (Sandbox Code Playgroud)

此外,strname=ph12go04330raa"应该屈服strresult="30"

我是 bash 脚本的新手,我不知道从哪里开始进行这样的字符串模式匹配。你有什么建议吗?

jor*_*anm 32

您可以在 bash(3.0 或更高版本)中使用正则表达式来完成此操作:

if [[ $strname =~ 3(.+)r ]]; then
    strresult=${BASH_REMATCH[1]}
else
    echo "unable to parse string $strname"
fi
Run Code Online (Sandbox Code Playgroud)

在 bash 中,来自正则表达式的捕获组放置在特殊数组中BASH_REMATCH。元素 0 包含整个匹配项,元素 1 包含第一个捕获组的匹配项。


Sté*_*las 10

在标准sh语法中(因此可以与任何版本的bash或任何其他符合 POSIX 的 shell 一起使用),您可以执行以下操作:

case $strname in
  (*3*r*) 
    strresult=${strname#*3}
    strresult=${strresult%r*};;
  (*)
    printf >&2 '%s\n' "Unable to parse string $strname"
esac
Run Code Online (Sandbox Code Playgroud)

另请参阅旧的expr解决方案,它甚至适用于 35 岁的 Unices:

expr "x$strname" : 'x[^3]*3\(.*\)r'
Run Code Online (Sandbox Code Playgroud)

旧的怪癖expr是,如果匹配失败你会得到一个非零退出状态(罚款),但你也可以得到一个非零退出状态,如果返回的字符串解析为0(像strname=zz300rzz)。