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

Bash中mapfile导入数组与内联数组字符串比较结果异常原因求解

核心原因

你遇到的匹配异常是Windows与Linux/WSL的换行符格式不兼容导致的:

  • 你在Windows环境下创建的domains.txt、blacklist.txt默认使用CRLF(\r\n)作为行结束符,而Linux/WSL下的文本默认使用LF(\n)作为行结束符。
  • mapfile -t参数只会移除每行末尾的\n,不会移除前置的\r(回车符),因此从文件导入的BLACKLIST数组元素实际为domain1.no\r、domain3.no\r,多了一个不可见的回车符,导致字符串匹配失败。
  • 唯一能正常匹配的domain5.no,是因为你的blacklist.txt末尾没有追加换行,最后一行的domain5.no末尾没有\r\n,不存在多余字符所以匹配成功。
解决办法

你可以任选以下一种方案修复:

方案1:转换文本文件换行格式(一劳永逸)

使用dos2unix工具把Windows格式的文本转为Linux格式:

  1. 安装工具:sudo apt update && sudo apt install dos2unix
  2. 转换文件:dos2unix domains.txt blacklist.txt
    转换完成后直接运行原脚本即可正常工作。

方案2:读取文件时直接过滤回车符(无需修改原文件)

修改原有的mapfile读取逻辑,用tr命令删除所有不可见的\r字符:

mapfile -t DOMAINS < <(tr -d '\r' < domains.txt)
mapfile -t BLACKLIST < <(tr -d '\r' < blacklist.txt)

方案3:优化匹配逻辑(更严谨,避免误匹配)

因为你的DOMAINS数组每行第一个字段才是域名,你可以直接提取第一个字段做匹配,同时过滤回车符,就算后续配置文件有格式小问题也能正常工作:
修改test_function部分逻辑:

function test_function ()
{
    # 提取传入参数的第一个字段作为域名,同时删除回车符
    host=${1%% *}
    host=${host//$'\r'/}
    is_blacklisted=0
    
    for domain in "${BLACKLIST[@]}"; do
        # 同样先删除黑名单条目的回车符
        domain=${domain//$'\r'/}
        if [[ "$host" == "$domain" ]]; then
            is_blacklisted=1
            # 匹配到后可以提前退出循环,提升效率
            break
        fi
    done
    
    if [ $is_blacklisted -eq 1 ]; then
        printf "%s\n" "$host is blacklisted"
    else
        printf "%s\n" "$host is NOT blacklisted"
    fi
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 05:54:01