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

如何在Bash脚本中从现有字符串提取唯一字符的字符串?

Bash 字符串去重(提取唯一字符)

问题描述

现有字符串:

explicit_borders="\"\"''()"

需要生成仅包含唯一字符的结果字符串:

distinct_border_chars="\"'()"  # 仅保留唯一字符集合

疑问:是否必须逐个遍历字符,仅当结果字符串中不存在该字符时才添加?有没有更简便的Bash专属解决方案?

更新要求:优先选择**基于Bash内置命令、不创建额外子shell(不使用管道|和命令替换$())**的方案,这类方案性能更优;同时最好不使用here-strings<<< ...(会创建临时文件影响性能)。也可提供其他简洁方案作为补充。

解决方案

1. 高性能纯内置方案(无额外子shell/临时文件)

这种方案完全依赖Bash内置语法,没有调用外部命令,性能最优:

explicit_borders="\"\"''()"
distinct_border_chars=""

# 逐个遍历原字符串的每个字符
for (( i=0; i<${#explicit_borders}; i++ )); do
    # 提取当前位置的单个字符
    char="${explicit_borders:i:1}"
    # 检查字符是否已在结果字符串中,不存在则追加
    if [[ "$distinct_border_chars" != *"$char"* ]]; then
        distinct_border_chars+="$char"
    fi
done

# 验证结果
echo "$distinct_border_chars"  # 输出:"'()

核心逻辑:用${string:index:length}语法提取单个字符,通过[[ ... != *...* ]]的模式匹配检查字符是否已存在,不存在则追加到结果变量中。全程无外部进程开销,适合处理大字符串或对性能敏感的场景。

2. 简洁方案(使用外部工具,适合快速编写)

如果对性能要求不高,追求代码简洁,可以用以下几种方式:

方式一:fold + sort -u + tr

explicit_borders="\"\"''()"
distinct_border_chars=$(fold -w1 <<< "$explicit_borders" | sort -u | tr -d '\n')
echo "$distinct_border_chars"  # 输出:"'()

逻辑:fold -w1把字符串拆分成每行一个字符,sort -u排序并去重,tr -d '\n'把多行合并回单行。缺点是会创建多个子shell,性能略低。

方式二:awk 数组去重

explicit_borders="\"\"''()"
distinct_border_chars=$(awk -v s="$explicit_borders" '{
    for(i=1;i<=length(s);i++){
        c=substr(s,i,1)
        if(!seen[c]++) printf c
    }
}')
echo "$distinct_border_chars"

逻辑:利用awk的关联数组seen记录已出现的字符,遍历字符串提取每个字符,未记录过则输出。只创建一个子shell,性能比方式一略好。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 10:41:13