【发布时间】:2016-07-30 18:13:06
【问题描述】:
在将敏感值写入日志文件之前,我正在尝试在命令行中屏蔽键、令牌等敏感值。
例如:
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 但有分隔符限制,即当 '+' 在 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 个字符)?
以下是后来添加的,以响应您的 cmets 和答案 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
这是第一个代码 sn-p,它显示了 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 表明两者都失败了
这是第二个代码 sn-p,它显示了如何解决 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....
【问题讨论】:
-
忘了说,echo "${MY_CMD/${MY_TOKEN}/XXXXXX}" 工作正常,ShellCheck 没问题,但 checkbashisms 抱怨 (${parm/?/pat[/str] })。我只是想尽可能便携,希望你能帮忙:)
-
另见stackoverflow.com/q/29613304/1745001。你想要一个正则表达式匹配吗?如果是这样,请在 awk 中使用 sed 或正则表达式操作。如果不是,并且您实际上想要字符串匹配,则将 awk 与字符串函数一起使用。 edit您的问题包括简洁、可测试的样本输入和预期输出,以便我们为您提供帮助。
-
谢谢@EdMorton,我已经打包了一堆测试用例。我使用了来自 slicevinov 的 r.awk 并编写了两个代码 sn-ps 来演示导致问题的原因以及可以采取哪些措施来解决它。请参阅答案 1 中的详细信息。
-
不要只说“它失败了”,告诉我们它是如何失败的,这样我们就不必尝试解决它。您的
echo本身可能正在解释字符(提示:请改用printf)。要了解有关您遇到的问题的更多信息,请参阅 unix.stackexchange.com/questions/169716/…、stackoverflow.com/questions/29613304/…,并阅读 Arnold Robbins 的《Effective Awk Programming, 4th Edition》和 Chris Johnson 的《Shell Scripting Recipes》。