【问题标题】:sed find replace using bash arrays failssed 使用 bash 数组查找替换失败
【发布时间】:2015-04-07 09:16:17
【问题描述】:

我有三个文件,两个文件,每个文件有 2259 个 IP 地址。一个包含 137772 的文件。该脚本使用 sed 和 bash 数组和一个 for 循环来用不同的 IP 替换 access.log 中的 IP。运行几个小时后,脚本失败并出现以下错误:

sed: -e 表达式#1, char 0: 没有之前的正则表达式

uniq IP 地址的数量也少了六个 IP。

这是脚本:

#!/bin/bash
_ORGIFS=$IFS
IFS=$'\n'
_alIPs=($(<access.log.IPs)
_fIPs=($(<randomIPs.txt)
for (( _i=1; _i<=2259; _i++ ))
do 
  sed -i "s/${_alIPs[$_i]}/${_fIPs[$_i]}/g" access.log
done
IFS=$_ORGIFS

【问题讨论】:

    标签: bash sed


    【解决方案1】:

    bash 中的数组索引从 0 开始。当你说时

    for (( _i=1; _i<=2259; _i++ ))
    

    您忽略第一个条目并越过末尾,此时

    sed -i "s/${_alIPs[$_i]}/${_fIPs[$_i]}/g" access.log
    

    扩展到

    sed -i "s//something/g" access.log
    

    s 命令中的// 尝试重用以前使用的不存在的正则表达式,因此您会收到错误。

    解决办法是用

    for (( _i=0; _i<2259; _i++ ))
    

    ...不过,说真的,我会花一些时间考虑批量替换的方法。

    附录:

    sed -i -f <(paste access.log.IPs randomIPs.txt | awk '{ print "s/" $1 "/" $2 "/g" }') access.log
    

    (假设我没看错你的意图)

    【讨论】:

    • 或者,只需使用 awk 而不是 sed 进行进程替换。
    【解决方案2】:

    这是根据需要取自我自己的 bash 模板库使用:

    # parse a template and return it
    # 1st arg is template tags [array]
    # 2nd arg is replacement values for template tags [array]
    # 3rd arg is template file path
    # usage: TT=$(parseTemplate TAGS[@] REPLACE[@] $MAIL_TEMPLATE); echo $TT;
    function parseTemplate()
    {
        local _TAG=("${!1}")
        local _REPLACE=("${!2}")
        local _TEMPLATE="${3}"
        local _PATTERN=""
        local i
    
        if [[ ${#_TAG[@]} > 0 ]]; then
            _PATTERN="-e s#\%\%${_TAG[0]}\%\%#${_REPLACE[0]}#g"
            for (( i = 1 ; i < ${#_TAG[@]} ; i++ ))
            do
                _PATTERN="${_PATTERN}; s#\%\%${_TAG[${i}]}\%\%#${_REPLACE[${i}]}#g"
            done
    
            local SED=`which sed`
            $SED "${_PATTERN}" < "${_TEMPLATE}"
        else
            local CAT=`which cat`
            $CAT "${_TEMPLATE}"
        fi
    }
    

    模板替换标签有这种格式:%%TAG%% 可以改变这个,但这就是这个函数使用的

    示例模板(文件或文本):

    Hello %%NAME%%, your location is %%LOCATION%%
    
    
    TAGS = ('NAME' 'LOCATION');
    REPLACE = ('Nikos' 'GR')
    TT=$(parseTemplate TAGS[@] REPLACE[@] $MAIL_TEMPLATE); 
    echo $TT;
    

    http://www.thegeekstuff.com/2010/06/bash-array-tutorial/

    【讨论】:

    • SED=`which sed`; $SED ... 与仅调用 command sed ... 相比没有任何优势
    • @glennjackman,好的,这只是处理一些极端情况,即命令不在 /bin 路径中(在各种环境中),可以轻松删除这些额外代码
    猜你喜欢
    • 2020-02-03
    • 2012-12-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-05
    • 1970-01-01
    • 2021-10-06
    相关资源
    最近更新 更多