![在 bash 脚本中根据模式提取字符串](https://linux22.com/image/28614/%E5%9C%A8%20bash%20%E8%84%9A%E6%9C%AC%E4%B8%AD%E6%A0%B9%E6%8D%AE%E6%A8%A1%E5%BC%8F%E6%8F%90%E5%8F%96%E5%AD%97%E7%AC%A6%E4%B8%B2.png)
在 bash 中,假设我有一个字符串strname
:
strname="ph7go04325r"
我想提取第一的 "3"
性格和最后的 "r"
中的字符strname
,将结果保存在字符串中strresult
。在上面的示例中,结果strresult
将是:
strresult="25"
第一个"3"
字符是不是必须位于 中的字符串位置 8 strname
;同样,最后一个"r"
是不是必然位于字符串位置 11。因此,以下两个字符串都strname
应该产生strresult="25"
:
strname="ph11go04325raa"
strname="325r"
strname="rgo04325raa"
另外,strname=ph12go04330raa"
应该产生strresult="30"
.
我是 bash 脚本新手,我不知道从哪里开始进行这样的字符串模式匹配。你有什么建议吗?
答案1
您可以在 bash(3.0 或更高版本)中使用正则表达式来完成此操作:
if [[ $strname =~ 3(.+)r ]]; then
strresult=${BASH_REMATCH[1]}
else
echo "unable to parse string $strname"
fi
在 bash 中,来自正则表达式的捕获组被放置在特殊的 array 中BASH_REMATCH
。元素 0 包含整个匹配项,元素 1 包含第一个捕获组的匹配项。
答案2
在标准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
另请参阅旧的expr
解决方案,它甚至可以在 35 年历史的 Unices 上运行:
expr "x$strname" : 'x[^3]*3\(.*\)r'
老人怪癖with 的意思是,如果匹配失败,您将获得非零退出状态(很好),但如果返回的字符串解析为 0(如 with ),expr
您也会获得非零退出状态。strname=zz300rzz