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

如何直接对比Bash数组元素的前N个字符并输出匹配项?

问题描述

假设存在两个Bash数组A和B,可通过读取目录下的txt文件生成,或直接声明定义:

通过目录生成数组

  • 目录A中执行以下脚本生成数组A:
#!/bin/bash
A=( $(ls *txt) )

目录A包含的文件:

fox_abdce.txt
rabbit_abdce.txt
lemom_asnrndna.txt
  • 目录B中执行以下脚本生成数组B:
#!/bin/bash
B=( $(ls *txt) )

目录B包含的文件:

fox_zzzzzz.txt
rabbit_zzzedd.txt
lemom_kokoijijim.txt

直接声明数组

也可直接通过代码声明数组:

#!/bin/bash
declare -a A=([0]="fox_abcde.txt" [1]="lemom_asnrndna.txt" [2]="rabbit_abcde.txt") 
declare -a B=([0]="fox_zzzzzz.txt" [1]="lemom_kokoijijim.txt" [2]="rabbit_zzzedd.txt")

需求:对比两个数组的所有元素,判断其前3个字符是否一致,输出所有匹配元素,支持两种格式:

  • 格式一(分组列出):
fox_abdce.txt
rabbit_abdce.txt
lemom_asnrndna.txt

fox_zzzzzz.txt
rabbit_zzzedd.txt
lemom_kokoijijim.txt
  • 格式二(对应项并排):
fox_abdce.txt             fox_zzzzzz.txt
rabbit_abdce.txt          rabbit_zzzedd.txt
lemom_asnrndna.txt        lemom_kokoijijim.txt

此前处理CSV文件两列前N字符匹配的AWK方法如下,需将该逻辑迁移到Bash数组:
设置环境变量:

#!/bin/bash
export NUMBER_OF_DIGITS=3

匹配项输出:

awk -F, '{if(substr($1, 1, ENVIRON["NUMBER_OF_DIGITS"]) == substr($2, 1, ENVIRON["NUMBER_OF_DIGITS"])) print}' file.csv

不匹配项输出:

awk -F, '{if(substr($1, 1, ENVIRON["NUMBER_OF_DIGITS"]) != substr($2, 1, ENVIRON["NUMBER_OF_DIGITS"])) print}' file.csv

解决方案

首先统一设置匹配的字符数变量:

export NUMBER_OF_DIGITS=3

实现格式一(分组列出)

遍历数组筛选出前缀匹配的元素,分两组输出:

#!/bin/bash
export NUMBER_OF_DIGITS=3

# 替换为目录生成数组的代码也可
declare -a A=([0]="fox_abcde.txt" [1]="lemom_asnrndna.txt" [2]="rabbit_abcde.txt") 
declare -a B=([0]="fox_zzzzzz.txt" [1]="lemom_kokoijijim.txt" [2]="rabbit_zzzedd.txt")

# 输出数组A中所有匹配元素
for elem in "${A[@]}"; do
    prefix="${elem:0:$NUMBER_OF_DIGITS}"
    for b_elem in "${B[@]}"; do
        if [[ "${b_elem:0:$NUMBER_OF_DIGITS}" == "$prefix" ]]; then
            echo "$elem"
            break
        fi
    done
done

echo # 空行分隔两组

# 输出数组B中所有匹配元素
for elem in "${B[@]}"; do
    prefix="${elem:0:$NUMBER_OF_DIGITS}"
    for a_elem in "${A[@]}"; do
        if [[ "${a_elem:0:$NUMBER_OF_DIGITS}" == "$prefix" ]]; then
            echo "$elem"
            break
        fi
    done
done

实现格式二(对应项并排)

先为数组B建立前缀到元素的映射,再遍历数组A匹配输出:

#!/bin/bash
export NUMBER_OF_DIGITS=3

# 替换为目录生成数组的代码也可
declare -a A=([0]="fox_abcde.txt" [1]="lemom_asnrndna.txt" [2]="rabbit_abcde.txt") 
declare -a B=([0]="fox_zzzzzz.txt" [1]="lemom_kokoijijim.txt" [2]="rabbit_zzzedd.txt")

# 构建数组B的前缀-元素关联映射
declare -A b_prefix_map
for elem in "${B[@]}"; do
    prefix="${elem:0:$NUMBER_OF_DIGITS}"
    b_prefix_map["$prefix"]="$elem"
done

# 遍历数组A,匹配后格式化并排输出
for elem in "${A[@]}"; do
    prefix="${elem:0:$NUMBER_OF_DIGITS}"
    if [[ -n "${b_prefix_map[$prefix]}" ]]; then
        # 25为第一列宽度,可根据元素长度调整
        printf "%-25s %s\n" "$elem" "${b_prefix_map[$prefix]}"
    fi
done

高效实现(结合AWK)

若数组元素数量多,可将两个数组转为类似CSV的行结构,用AWK批量处理:

#!/bin/bash
export NUMBER_OF_DIGITS=3

declare -a A=([0]="fox_abcde.txt" [1]="lemom_asnrndna.txt" [2]="rabbit_abcde.txt") 
declare -a B=([0]="fox_zzzzzz.txt" [1]="lemom_kokoijijim.txt" [2]="rabbit_zzzedd.txt")

# 将两个数组元素按行对齐后传递给AWK匹配
paste <(printf "%s\n" "${A[@]}") <(printf "%s\n" "${B[@]}") | awk -F'\t' '{
    if(substr($1, 1, ENVIRON["NUMBER_OF_DIGITS"]) == substr($2, 1, ENVIRON["NUMBER_OF_DIGITS"])) {
        printf "%-25s %s\n", $1, $2
    }
}'

注:此方法适合两个数组元素数量相同、或已按前缀排序的场景。


内容的提问来源于stack exchange,提问作者Gabriel G.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 04:07:09