有人知道 gawk gsub 函数的局限性吗?
Is anyone aware of the limitations in the gawk gsub function?
我试图在将敏感值写入日志文件之前在命令行中屏蔽密钥、令牌等敏感值。
例如:
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 包含特定字符时,屏蔽将不起作用 and/or 会产生错误。一些特殊字符是:$ ^ * ( ) + [ ] | \ ?
以下工作正常
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 但存在分隔符限制,即当 '+' 在 MY_TOKEN[=17 中时=]
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
可能有更好更简单的方法来处理它,那就是 100% POSIX...
您可以使用 index
(its 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([=10=])
}
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
看起来这就是您要执行的操作:
$ 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([=10=],my_token) ) {
printf "%s%s", substr([=10=],1,start-1), m
[=10=] = substr([=10=],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"
这是将@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([=10=],my_token) ) {
printf "%s%s", substr([=10=],1,start-1), m
[=10=] = substr([=10=],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
从上面的脚本中删除以下行时,它会传递 "checkbashisms -fx" 以及 http://www.shellcheck.net/
printf 'Mask with bash built-in: %s\n' "${MY_CMD/${MY_TOKEN}/XXXXXX}"
上面一行只是为了展示两种方法之间的差异。
感谢大家的快速反馈并帮助我改进了我在 post.
中的沟通
我试图在将敏感值写入日志文件之前在命令行中屏蔽密钥、令牌等敏感值。
例如:
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 包含特定字符时,屏蔽将不起作用 and/or 会产生错误。一些特殊字符是:$ ^ * ( ) + [ ] | \ ?
以下工作正常
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 但存在分隔符限制,即当 '+' 在 MY_TOKEN[=17 中时=]
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
可能有更好更简单的方法来处理它,那就是 100% POSIX...
您可以使用 index
(its 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([=10=])
}
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
看起来这就是您要执行的操作:
$ 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([=10=],my_token) ) {
printf "%s%s", substr([=10=],1,start-1), m
[=10=] = substr([=10=],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"
这是将@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([=10=],my_token) ) {
printf "%s%s", substr([=10=],1,start-1), m
[=10=] = substr([=10=],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
从上面的脚本中删除以下行时,它会传递 "checkbashisms -fx" 以及 http://www.shellcheck.net/
printf 'Mask with bash built-in: %s\n' "${MY_CMD/${MY_TOKEN}/XXXXXX}"
上面一行只是为了展示两种方法之间的差异。
感谢大家的快速反馈并帮助我改进了我在 post.