You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Bash脚本提取$...$分隔符间文本?现有代码无效

问题分析与解决方案

你的问题核心在于正则表达式的语法环境不匹配,以及对提取目标的处理偏差,我来拆解一下:

为什么原代码失效?

  1. 正则语法环境差异:
    你在regex101测试的正则大概率用的是PCRE(Perl兼容正则)或ERE(扩展正则)模式,但bash默认的grep使用的是BRE(基础正则表达式)。在BRE中,()是字面字符(不是捕获组),所以你的正则\$([^\$]*)\$实际是在匹配$(xxx)$这种带括号的格式,但你的测试文本里根本没有括号,自然匹配不到。
  2. 提取目标偏差:
    就算正则能匹配到,原代码会把包含$的整个串(比如$bfc2439c621353$)存入数组,而你需要的是去掉前后$的中间内容,这也不符合预期。

至于[0-9]\+能正常工作,是因为这个正则不需要捕获组,GNU grep的BRE模式也支持\+作为量词(多数Linux系统用的是GNU grep),所以能直接匹配到数字串。

修正方案

下面提供几种可行的解决方式,都能得到你想要的bfc2439c621353 629f结果:

方法1:使用PCRE模式的grep(推荐)

GNU grep支持-P参数启用PCRE模式,配合\K正向预查可以直接跳过前面的$,只提取中间内容:

#!/bin/bash
array=($(grep -oP '\$\K[^\$]+' test.txt))
echo ${array[@]}
  • \$\K:匹配$后,丢弃该匹配结果,只保留后续的内容
  • [^\$]+:匹配任意非$的字符(至少一个)

方法2:使用sed提取捕获组

sed适合处理文本替换,通过捕获组提取$之间的内容:

#!/bin/bash
array=($(sed -n 's/.*\$\([^\$]*\)\$.*/\1/gp' test.txt))
echo ${array[@]}
  • -n:默认不输出行,只打印匹配替换后的内容
  • s/.*\$\([^\$]*\)\$.*/\1/g:全局替换,把整行内容替换为$之间捕获到的部分
  • p:打印替换后的结果

方法3:兼容基础正则的方案

如果你的系统不支持PCRE,也可以先用grep匹配整个$...$串,再用sed去掉前后的$:

#!/bin/bash
array=($(grep -o '\$[^\$]*\$' test.txt | sed 's/^\$\(.*\)\$$/\1/'))
echo ${array[@]}
  • 第一步grep -o '\$[^\$]*\$':匹配所有包含$的目标串
  • 第二步sed 's/^\$\(.*\)\$$/\1/':去掉每个串首尾的$

内容的提问来源于stack exchange,提问作者Glinka

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 08:17:26