使用 bash 数组的 sed 查找替换失败

sed find replace using bash arrays fails

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

sed:-e 表达式 #1,字符 0:没有先前的正则表达式

uniq IP地址数量也少了6个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模板库,按需使用:

# 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=""
    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/

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/"  "/"  "/g" }') access.log

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