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

Bash中d=${c//[^$b]}如何统计$c内指定字符$b的出现次数?

相关Bash统计脚本
#!/bin/bash

echo "The program checks the number of indicated letters"
echo "Enter the file name and path"
read a
c=$(cat $a)
echo "
Enter which letter is to be found. for examle 'a' "
read b
d=${c//[^$b]}
echo "The number of occurrences of the character is: " ${#d}
${c//[^$b]} 行逻辑拆解

你之前了解的[^...]匹配方括号范围外任意字符的规则是完全正确的,觉得逻辑矛盾,是因为没搞懂这行用的是Bash的参数扩展全局替换语法,走的是「反向删除非目标字符」的统计思路,不是正向匹配目标字符计数。

逐段拆解语法规则:

  • ${var//match/replace} 是Bash原生的全局字符串替换语法:会把变量var中所有符合match规则的内容,全部替换为replace位置的内容;如果replace位置留空,效果就是删除所有匹配到的内容。
  • 这行里的匹配规则是[^$b]:当你输入待统计字符比如a时,变量$b会展开为a,匹配规则就变成[^a],即匹配所有不等于a的字符。
  • 因为替换位置是空值,这行实际执行的操作是:把读入的文件内容变量c里,所有不是你指定字符的内容全部删掉,最终变量d里剩下的字符,全是你要统计的目标字符。
  • 末尾的${#d}是Bash取变量字符串长度的语法,剩下的字符串全是目标字符,长度值自然就是该字符在文件中的总出现次数。
参考资料的误区说明

你查到的"[^d]"匹配b到d范围外字符的描述是错误的,混淆了方括号通配的两个不同规则:

  • 只有方括号内出现[起始字符-结束字符]这种横杠连接两个字符的写法时,才代表匹配指定的字符范围,比如[b-d]才是匹配b、c、d三个字符。
  • 如果^是方括号内的第一个字符,它的唯一作用是对匹配集合取反,和范围匹配没有任何关系:[^a]就是匹配所有不是a的字符,[^b-d]才是匹配所有不在b到d范围内的字符。

举个实际运行的例子方便理解:

  1. 假设目标文件内容是abac123a,读入后c变量值就是这段文本
  2. 你输入待统计字符a,此时$b展开为a,匹配规则为[^a]
  3. 所有非a的字符b/c/1/2/3会被全部删除,最终d变量值为aaa
  4. 取d的长度得到3,就是文件中字符a的出现次数,和脚本实际运行结果一致。

补充说明:这个脚本存在小缺陷,如果你输入的待查找内容是多个字符,统计结果会不符合预期——因为方括号通配里[^abc]代表匹配所有不是a/b/c的字符,删除后剩下的是所有a/b/c字符,统计的是这几个字符的总出现次数,不是单个字符的计数。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 14:45:35