如何在Bash中将重复单词处理为dup,dup(1),dup(2)格式?
解决Bash字符串重复元素添加序号的问题
我来帮你搞定这个需求~你已经迈出了正确的第一步:把逗号分隔的字符串拆成数组,接下来只需要跟踪每个元素的出现次数,就能给重复元素加上递增序号了。
完整实现代码
string="lisp,pascal,lisp,bash,bash,bash,lisp" set -f # 禁用通配符扩展,避免特殊字符(比如*)被意外解析 array=(${string//,/ }) # 声明关联数组,用于记录每个元素已出现的次数(Bash 4.0+支持) declare -A element_counter # 遍历数组处理每个元素 processed_result="" for elem in "${array[@]}"; do # 初始化计数:如果元素是第一次出现,计数设为0 [[ -z "${element_counter[$elem]}" ]] && element_counter[$elem]=0 if [[ ${element_counter[$elem]} -eq 0 ]]; then # 第一次出现,直接保留原元素 processed_result+="${elem}," else # 重复出现,添加序号(序号=当前计数) processed_result+="${elem}(${element_counter[$elem]})," fi # 计数自增,为下一次出现做准备 ((element_counter[$elem]++)) done # 去掉结果末尾多余的逗号,输出最终内容 echo "${processed_result%,}"
代码关键点解释
- 关联数组
element_counter:用来存储每个元素已经出现的次数,比如第一次遇到lisp时计数为0,第二次遇到时计数已经变成1,所以输出lisp(1)。 set -f:非常重要!它会禁用Bash的通配符扩展,避免如果字符串里包含*、?这类字符时,被解析成目录文件列表。- 末尾逗号处理:用
${processed_result%,}去掉最后一个多余的逗号,比用sed更高效。
运行结果
执行这段代码后,会输出你期望的结果:
lisp,pascal,lisp(1),bash,bash(1),bash(2),lisp(2)
兼容低版本Bash(可选)
如果你的Bash版本低于4.0(不支持关联数组),可以用普通数组+循环计数的方式替代,不过这种方法效率稍低:
string="lisp,pascal,lisp,bash,bash,bash,lisp" set -f array=(${string//,/ }) processed_result="" for i in "${!array[@]}"; do current_elem=${array[$i]} # 统计当前元素在之前出现的次数 count=0 for ((j=0; j<i; j++)); do [[ ${array[$j]} == "$current_elem" ]] && ((count++)) done if [[ $count -eq 0 ]]; then processed_result+="${current_elem}," else processed_result+="${current_elem}($count)," fi done echo "${processed_result%,}"
内容的提问来源于stack exchange,提问作者carlson john
相关产品推荐
相关产品推荐

