有人知道gawk gsub函数的局限性吗?

时间:2016-07-30 18:13:06

标签: awk sed gawk

在将其写入日志文件之前,我试图在命令行中屏蔽敏感值,如键,令牌等等。
例如:

MY_TOKEN='MaskThisPlease'
MY_CMD="my_command ${MY_TOKEN} SomeOtherString"
echo "${MY_CMD}" | gawk -v k="${MY_TOKEN}" -v m="XXXXXX" '{gsub(k,m);print}'

结果是:

my_command XXXXXX SomeOtherString

现在,当MY_TOKEN包含特定字符时,屏蔽将不起作用和/或将产生错误。一些特殊字符是:$ ^ *()+ [] | \?

以下工作正常

MY_TOKEN='MaskThisPlease_SomeABCs_Some123s_SomeOther//!!@@##%%_--==``~~{{}}::;;""<<>>,,..zzzzzzzzzzzzzzzzzzzzzzzzz'
MY_CMD="my_command ${MY_TOKEN} SomeOtherString"
echo "${MY_CMD}" | awk -v k="${MY_TOKEN}" -v m="XXXXXX" '{gsub(k,m);print}'

我尝试了 sed ,但是有了分隔符限制,即当&#39; +&#39;在 MY_TOKEN

MY_TOKEN='MaskThisPlease_SomeABCs_Some123s_SomeOther+PlusSign+here'
MY_CMD="my_command ${MY_TOKEN} SomeOtherString"
echo "${MY_CMD}" | sed "s+${MY_TOKEN}+XXXXXX+g"

sed: -e expression #1, char 55: unknown option to `s'

所以,我的问题是
有没有其他方法可以执行掩码而不会遇到上述情况并且没有大小限制(MY_TOKEN可能是700个字符)?

以下是在您的评论和答案1的回复中添加的:
我刚加入Stack Overflow,这是我的第一篇帖子。我无法将测试数据附加为r.dat。 r.dat中的每一行都是我的令牌的值(详见下面的答案1)。

MaskThisPlease_SomeABCs_Some123s_SomeOther//!!@@##%%_--==``~~{{}}::;;""<<>>,,..zzzzzzzzzzzzzzzzzzzzzzzzz
AlphaNumericCharacters1234567890
''MaskThisPlease_SomeABCs_Some123s_SomeOther//!!@@##%%_--==``~~{{}}::;;""<<>>,,..zzzzzzzzzzzzzzzzzzzzzzzzz''
MaskThisPlease_SomeABCs_Some123s_SomeOther//!!@@##%%_--==``~~{{}}::;;""<<>>,,..$zzzzzzzzzzzzzzzzzzzzzzzzz
MaskThisPlease_SomeABCs_Some123s_SomeOther//!!@@##%%_--==``~~{{}}::;;""<<>>,,..$^zzzzzzzzzzzzzzzzzzzzzzzzz
MaskThisPlease_SomeABCs_Some123s_SomeOther//!!@@##%%_--==``~~{{}}::;;""<<>>,,..$^zzzzzzzzzzzzzzzzzzzzzzzzz
MaskThisPlease_SomeABCs_Some123s_SomeOther//!!@@##%%_--==``~~{{}}::;;""<<>>,,..$^(zzzzzzzzzzzzzzzzzzzzzzzzz
MaskThisPlease_SomeABCs_Some123s_SomeOther//!!@@##%%_--==``~~{{}}::;;""<<>>,,..$^()zzzzzzzzzzzzzzzzzzzzzzzzz
MaskThisPlease_SomeABCs_Some123s_SomeOther//!!@@##%%_--==``~~{{}}::;;""<<>>,,..$^()+zzzzzzzzzzzzzzzzzzzzzzzzz
MaskThisPlease_SomeABCs_Some123s_SomeOther//!!@@##%%_--==``~~{{}}::;;""<<>>,,..$^()+[zzzzzzzzzzzzzzzzzzzzzzzzz
MaskThisPlease_SomeABCs_Some123s_SomeOther//!!@@##%%_--==``~~{{}}::;;""<<>>,,..$^()+[]zzzzzzzzzzzzzzzzzzzzzzzzz
MaskThisPlease_SomeABCs_Some123s_SomeOther//!!@@##%%_--==``~~{{}}::;;""<<>>,,..$^()+[]|zzzzzzzzzzzzzzzzzzzzzzzzz
MaskThisPlease_SomeABCs_Some123s_SomeOther//!!@@##%%_--==``~~{{}}::;;""<<>>,,..$^()+[]|?zzzzzzzzzzzzzzzzzzzzzzzzz
MaskThisPlease_SomeABCs_Some123s_SomeOther//!!@@##%%_--==``~~{{}}::;;""<<>>,,..$^()+[]|?*zzzzzzzzzzzzzzzzzzzzzzzzz
MaskThisPlease_SomeABCs_Some123s_SomeOther//!!@@##%%_--==``~~{{}}::;;""<<>>,,..$^()+[]|?**zzzzzzzzzzzzzzzzzzzzzzzzz
MaskThisPlease_SomeABCs_Some123s_SomeOther//!!@@##%%_--==``~~{{}}::;;""<<>>,,..$^()+[]|?*)zzzzzzzzzzzzzzzzzzzzzzzzz
MaskThisPlease_SomeABCs_Some123s_SomeOther//!!@@##%%_--==``~~{{}}::;;""<<>>,,..$^()+[]|?*.zzzzzzzzzzzzzzzzzzzzzzzzz
MaskThisPlease_SomeABCs_Some123s_SomeOther//!!@@##%%_--==``~~{{}}::;;""<<>>,,..$^()+[]|?.*zzzzzzzzzzzzzzzzzzzzzzzzz
MaskThisPlease_SomeABCs_Some123s_SomeOther//!!@@##%%_--==``~~{{}}::;;""<<>>,,..$^()+[]|?*(zzzzzzzzzzzzzzzzzzzzzzzzz
MaskThisPlease_SomeABCs_Some123s_SomeOther//!!@@##%%_--==``~~{{}}::;;""<<>>,,..$^()+[]|?\\zzzzzzzzzzzzzzzzzzzzzzzzz
MaskThisPlease_SomeABCs_Some123s_SomeOther//!!@@##%%_--==``~~{{}}::;;""<<>>,,..$^()+[]|?\zzzzzzzzzzzzzzzzzzzzzzzzz

这是第一个代码片段,它显示了r.awk和bash内置替换函数中的一些限制

clear
# Read one by one my test cases
I=0
cat ./r.dat | while IFS= read -r MY_TOKEN
do
    I=$((I+1))

    echo
    echo "#########################################################"
    echo "${I}) MyToken is ${MY_TOKEN}"
    echo "#########################################################"

    # Build my command including the value of my token
    MY_CMD="my_command ${MY_TOKEN} SomeOtherString"

    printf "Mask with gawk function: "
      echo "${MY_CMD}" | gawk -F'\n' -v k="${MY_TOKEN}" -v m="XXXXXX" -f ./r.awk 2>/dev/null

    printf "Mask with bash built-in: "
      echo "${MY_CMD/${MY_TOKEN}/XXXXXX}"
done

测试用例19表明r.awk比bash内置替换功能更好 测试案例20显示两者都失败了 测试案例21显示两者都失败

这是第二个代码片段,展示了如何修复r.awk和bash内置替换函数中的问题

clear
# Read one by one my test cases
I=0
cat ./r.dat | while IFS= read -r MY_TOKEN
do
    I=$((I+1))

    # Escape RegEx characters
    MY_TOKEN_ESCAPED=$(echo ${MY_TOKEN} | sed 's:[][\/.^$*]:\\&:g')

    echo
    echo "#########################################################"
    echo "${I}) MyToken is ${MY_TOKEN}"
    echo "${I}) Escaped is ${MY_TOKEN_ESCAPED}"
    echo "#########################################################"

    # Build my command including the value of my token
    MY_CMD="my_command ${MY_TOKEN} SomeOtherString"

    printf "Mask with gawk function: "
      echo "${MY_CMD}" | gawk -F'\n' -v k="${MY_TOKEN_ESCAPED}" -v m="XXXXXX" -f ./r.awk 2>/dev/null

    printf "Mask with bash built-in: "
      echo "${MY_CMD/${MY_TOKEN_ESCAPED}/XXXXXX}"
done

可能会有更好的&amp;处理它的简单方法以及100%POSIX ....

3 个答案:

答案 0 :(得分:1)

您可以使用indexits second argument是字符串而不是正则表达式)并从文件中读取密钥。这是一个例子。创建四个文件:

<强> r.awk

BEGIN {
    getline k < kfile; close(kfile)
    n = length(k)
}

function process(rst,   i, pre, ans) {
    while (i=index(rst, k)) {
        pre = substr(rst, 1,  i-1)
        rst = substr(rst, i + n)
        ans = ans pre m
    }
    return ans rst
}

{
    print process($0)
}

<强> r.sh

awk -v kfile=r.key -v m=XXX  -f r.awk r.dat

<强> r.dat

test\t\tMaskThisPlease_SomeABCs_Some123s_SomeOther//!!@@##%%_--==``~~{{}}::;;""<<>>,,..zzzzzzzzzzzzzzzzzzzzzzzzztest

<强> r.key

\t\tMaskThisPlease_SomeABCs_Some123s_SomeOther//!!@@##%%_--==``~~{{}}::;;""<<>>,,..zzzzzzzzzzzzzzzzzzzzzzzzz

运行它 sh r.sh

预期产出:

testXXXtest

答案 1 :(得分:0)

看起来这就是你要做的事情:

$ cat tst.sh
while IFS= read -r my_token
do
    old_my_cmd="my_command $my_token SomeOtherString"

    new_my_cmd=$(
        printf '%s\n' "$old_my_cmd" |
        awk -v m='XXXXXX' '
            BEGIN {
                my_token=ARGV[1]; ARGV[1]=""; ARGC--
                lgth = length(my_token)
            }
            {
                while ( start = index($0,my_token) ) {
                    printf "%s%s", substr($0,1,start-1), m
                    $0 = substr($0,start+lgth)
                }
                print
            }
        ' "$my_token"
    )

    printf 'old_my_cmd="%s"\n' "$old_my_cmd"
    printf 'new_my_cmd="%s"\n' "$new_my_cmd"
    printf "\n"

done < r.dat

$ ./tst.sh
old_my_cmd="my_command MaskThisPlease_SomeABCs_Some123s_SomeOther//!!@@##%%_--==``~~{{}}::;;""<<>>,,..zzzzzzzzzzzzzzzzzzzzzzzzz SomeOtherString"
new_my_cmd="my_command XXXXXX SomeOtherString"

old_my_cmd="my_command AlphaNumericCharacters1234567890 SomeOtherString"
new_my_cmd="my_command XXXXXX SomeOtherString"

old_my_cmd="my_command ''MaskThisPlease_SomeABCs_Some123s_SomeOther//!!@@##%%_--==``~~{{}}::;;""<<>>,,..zzzzzzzzzzzzzzzzzzzzzzzzz'' SomeOtherString"
new_my_cmd="my_command XXXXXX SomeOtherString"

old_my_cmd="my_command MaskThisPlease_SomeABCs_Some123s_SomeOther//!!@@##%%_--==``~~{{}}::;;""<<>>,,..$zzzzzzzzzzzzzzzzzzzzzzzzz SomeOtherString"
new_my_cmd="my_command XXXXXX SomeOtherString"

old_my_cmd="my_command MaskThisPlease_SomeABCs_Some123s_SomeOther//!!@@##%%_--==``~~{{}}::;;""<<>>,,..$^zzzzzzzzzzzzzzzzzzzzzzzzz SomeOtherString"
new_my_cmd="my_command XXXXXX SomeOtherString"

old_my_cmd="my_command MaskThisPlease_SomeABCs_Some123s_SomeOther//!!@@##%%_--==``~~{{}}::;;""<<>>,,..$^zzzzzzzzzzzzzzzzzzzzzzzzz SomeOtherString"
new_my_cmd="my_command XXXXXX SomeOtherString"

old_my_cmd="my_command MaskThisPlease_SomeABCs_Some123s_SomeOther//!!@@##%%_--==``~~{{}}::;;""<<>>,,..$^(zzzzzzzzzzzzzzzzzzzzzzzzz SomeOtherString"
new_my_cmd="my_command XXXXXX SomeOtherString"

old_my_cmd="my_command MaskThisPlease_SomeABCs_Some123s_SomeOther//!!@@##%%_--==``~~{{}}::;;""<<>>,,..$^()zzzzzzzzzzzzzzzzzzzzzzzzz SomeOtherString"
new_my_cmd="my_command XXXXXX SomeOtherString"

old_my_cmd="my_command MaskThisPlease_SomeABCs_Some123s_SomeOther//!!@@##%%_--==``~~{{}}::;;""<<>>,,..$^()+zzzzzzzzzzzzzzzzzzzzzzzzz SomeOtherString"
new_my_cmd="my_command XXXXXX SomeOtherString"

old_my_cmd="my_command MaskThisPlease_SomeABCs_Some123s_SomeOther//!!@@##%%_--==``~~{{}}::;;""<<>>,,..$^()+[zzzzzzzzzzzzzzzzzzzzzzzzz SomeOtherString"
new_my_cmd="my_command XXXXXX SomeOtherString"

old_my_cmd="my_command MaskThisPlease_SomeABCs_Some123s_SomeOther//!!@@##%%_--==``~~{{}}::;;""<<>>,,..$^()+[]zzzzzzzzzzzzzzzzzzzzzzzzz SomeOtherString"
new_my_cmd="my_command XXXXXX SomeOtherString"

old_my_cmd="my_command MaskThisPlease_SomeABCs_Some123s_SomeOther//!!@@##%%_--==``~~{{}}::;;""<<>>,,..$^()+[]|zzzzzzzzzzzzzzzzzzzzzzzzz SomeOtherString"
new_my_cmd="my_command XXXXXX SomeOtherString"

old_my_cmd="my_command MaskThisPlease_SomeABCs_Some123s_SomeOther//!!@@##%%_--==``~~{{}}::;;""<<>>,,..$^()+[]|?zzzzzzzzzzzzzzzzzzzzzzzzz SomeOtherString"
new_my_cmd="my_command XXXXXX SomeOtherString"

old_my_cmd="my_command MaskThisPlease_SomeABCs_Some123s_SomeOther//!!@@##%%_--==``~~{{}}::;;""<<>>,,..$^()+[]|?*zzzzzzzzzzzzzzzzzzzzzzzzz SomeOtherString"
new_my_cmd="my_command XXXXXX SomeOtherString"

old_my_cmd="my_command MaskThisPlease_SomeABCs_Some123s_SomeOther//!!@@##%%_--==``~~{{}}::;;""<<>>,,..$^()+[]|?**zzzzzzzzzzzzzzzzzzzzzzzzz SomeOtherString"
new_my_cmd="my_command XXXXXX SomeOtherString"

old_my_cmd="my_command MaskThisPlease_SomeABCs_Some123s_SomeOther//!!@@##%%_--==``~~{{}}::;;""<<>>,,..$^()+[]|?*)zzzzzzzzzzzzzzzzzzzzzzzzz SomeOtherString"
new_my_cmd="my_command XXXXXX SomeOtherString"

old_my_cmd="my_command MaskThisPlease_SomeABCs_Some123s_SomeOther//!!@@##%%_--==``~~{{}}::;;""<<>>,,..$^()+[]|?*.zzzzzzzzzzzzzzzzzzzzzzzzz SomeOtherString"
new_my_cmd="my_command XXXXXX SomeOtherString"

old_my_cmd="my_command MaskThisPlease_SomeABCs_Some123s_SomeOther//!!@@##%%_--==``~~{{}}::;;""<<>>,,..$^()+[]|?.*zzzzzzzzzzzzzzzzzzzzzzzzz SomeOtherString"
new_my_cmd="my_command XXXXXX SomeOtherString"

old_my_cmd="my_command MaskThisPlease_SomeABCs_Some123s_SomeOther//!!@@##%%_--==``~~{{}}::;;""<<>>,,..$^()+[]|?*(zzzzzzzzzzzzzzzzzzzzzzzzz SomeOtherString"
new_my_cmd="my_command XXXXXX SomeOtherString"

old_my_cmd="my_command MaskThisPlease_SomeABCs_Some123s_SomeOther//!!@@##%%_--==``~~{{}}::;;""<<>>,,..$^()+[]|?\\zzzzzzzzzzzzzzzzzzzzzzzzz SomeOtherString"
new_my_cmd="my_command XXXXXX SomeOtherString"

old_my_cmd="my_command MaskThisPlease_SomeABCs_Some123s_SomeOther//!!@@##%%_--==``~~{{}}::;;""<<>>,,..$^()+[]|?\zzzzzzzzzzzzzzzzzzzzzzzzz SomeOtherString"
new_my_cmd="my_command XXXXXX SomeOtherString"

答案 2 :(得分:-1)

此处的第3段代码片段将@ EdMorton的方法整合到原始代码中

# Read one by one my test cases
I=0
cat ./r.dat | while IFS= read -r MY_TOKEN
do
    I=$((I+1))

    echo
    echo "#########################################################"
    printf '%s) MyToken is %s\n' "${I}" "${MY_TOKEN}"
    echo "#########################################################"

    # Build my command including the value of my token
    MY_CMD="my_command ${MY_TOKEN} SomeOtherString"

    MY_CMD_MASKED=$(
        printf '%s\n' "${MY_CMD}" |
        awk -v m='XXXXXX' '
            BEGIN {
                my_token=ARGV[1]; ARGV[1]=""; ARGC--
                lgth = length(my_token)
            }
            {
                while ( start = index($0,my_token) ) {
                    printf "%s%s", substr($0,1,start-1), m
                    $0 = substr($0,start+lgth)
                }
                print
            }
        ' "${MY_TOKEN}"
    )

    printf 'Mask with gawk function: %s\n' "${MY_CMD_MASKED}"
    printf 'Mask with bash built-in: %s\n' "${MY_CMD/${MY_TOKEN}/XXXXXX}"
done

以下是我们之前讨论过的测试案例19,20和21的结果:

#########################################################
19) MyToken is MaskThisPlease_SomeABCs_Some123s_SomeOther//!!@@##%%_--==``~~{{}}::;;""<<>>,,..$^()+[]|?*(zzzzzzzzzzzzzzzzzzzzzzzzz
#########################################################
Mask with gawk function: my_command XXXXXX SomeOtherString
Mask with bash built-in: my_command XXXXXX SomeOtherString

#########################################################
20) MyToken is MaskThisPlease_SomeABCs_Some123s_SomeOther//!!@@##%%_--==``~~{{}}::;;""<<>>,,..$^()+[]|?\\zzzzzzzzzzzzzzzzzzzzzzzzz
#########################################################
Mask with gawk function: my_command XXXXXX SomeOtherString
Mask with bash built-in: my_command MaskThisPlease_SomeABCs_Some123s_SomeOther//!!@@##%%_--==``~~{{}}::;;""<<>>,,..$^()+[]|?\\zzzzzzzzzzzzzzzzzzzzzzzzz SomeOtherString

#########################################################
21) MyToken is MaskThisPlease_SomeABCs_Some123s_SomeOther//!!@@##%%_--==``~~{{}}::;;""<<>>,,..$^()+[]|?\zzzzzzzzzzzzzzzzzzzzzzzzz
#########################################################
Mask with gawk function: my_command XXXXXX SomeOtherString
Mask with bash built-in: my_command MaskThisPlease_SomeABCs_Some123s_SomeOther//!!@@##%%_--==``~~{{}}::;;""<<>>,,..$^()+[]|?\zzzzzzzzzzzzzzzzzzzzzzzzz SomeOtherString

从上面的脚本中删除以下行时,它会传递&#34; checkbashisms -fx&#34;以及http://www.shellcheck.net/

printf 'Mask with bash built-in: %s\n' "${MY_CMD/${MY_TOKEN}/XXXXXX}"

以上几行只是为了证明两种方法之间的差异 谢谢大家的快速反馈,并帮助我改进我在这篇文章中的沟通。