如何在Bash脚本中用正则表达式与sed提取指定子字符串?
解决Bash中提取
key=[value]形式的value问题 我来帮你搞定这个提取问题,先看看你原来的命令哪里出了问题,再给你几个靠谱的解决方案。
你的错误原因
- 缺少捕获组:你想用
\1引用匹配的内容,但正则里根本没把要提取的value部分用括号\(...\)包裹起来,sed自然找不到对应的引用,所以报错invalid reference \1。 - 正则语法错误:
^*是错误写法,^表示行首,后面跟*(零或多个前导字符)没有意义,要匹配任意前缀内容应该用.*。[*^\[]这个字符类逻辑不对,你想匹配除了]之外的字符,正确写法是[^]]*(字符类里的^表示取反,直接排除])。
- sed选项缺失:默认sed会输出所有行,即使替换成功也会把整个行输出,你需要用
-n配合p选项只输出匹配替换后的内容。
方案一:用sed正确提取
要提取指定key对应的value,且不存在时返回空字符串,可以用这个命令:
# 提取key的value key_value=$(echo "$txt" | sed -n 's/.*key=\[\([^]]*\)\].*/\1/p; t; s/.*/"/p') # 提取number的value number_value=$(echo "$txt" | sed -n 's/.*number=\[\([^]]*\)\].*/\1/p; t; s/.*/"/p') # 提取text的value text_value=$(echo "$txt" | sed -n 's/.*text=\[\([^]]*\)\].*/\1/p; t; s/.*/"/p')
命令解释:
-n:只输出我们指定打印的内容s/.*key=\[\([^]]*\)\].*/\1/p:匹配任意前缀+key=[+捕获value(除]外的所有字符)+]+任意后缀,替换为捕获的value并打印t:如果前面的替换成功,就跳过后面的命令s/.*/"/p:如果前面没匹配到(即key不存在),就把整行替换为空字符串并打印
方案二:用Bash内置正则匹配(更高效)
其实不用调用sed,直接用Bash的内置正则匹配功能,更高效也更易读:
txt="something... key=[value] number=[0.42] ...other things... text=[foo] etc" # 提取key的value if [[ $txt =~ key=\[([^]]*)\] ]]; then key_value=${BASH_REMATCH[1]} else key_value="" fi # 提取number的value if [[ $txt =~ number=\[([^]]*)\] ]]; then number_value=${BASH_REMATCH[1]} else number_value="" fi # 提取不存在的键(比如nonexistent) if [[ $txt =~ nonexistent=\[([^]]*)\] ]]; then nonexistent_value=${BASH_REMATCH[1]} else nonexistent_value="" fi # 测试输出 echo "key_value: '$key_value'" echo "number_value: '$number_value'" echo "nonexistent_value: '$nonexistent_value'"
解释:
[[ $txt =~ pattern ]]:Bash的正则匹配语法,成功匹配后会把捕获组的内容存到BASH_REMATCH数组里${BASH_REMATCH[1]}:第一个捕获组的内容,也就是我们要的value- 如果匹配失败,就给变量赋值为空字符串
测试结果
运行上面的代码,输出会是:
key_value: 'value' number_value: '0.42' nonexistent_value: ''
内容的提问来源于stack exchange,提问作者T.L
相关产品推荐
相关产品推荐

