我想使用标准工具和bash打印Linux上的所有环境变量。如果变量长度大于5,我需要看到环境名称和掩码变量,最后3个字符可见(qwerty
->***rty
),如果小于5(或等于5),则屏蔽值为1个可见字符(zxc
->**c
)。
的例子:
FOO=qwerty
BAR=asdfghjkl
BAZ=zxc
我希望这个命令打印:
FOO=***rty
BAR=******jkl
BAZ=**c
原值和掩码的长度在这里是一样的
此刻,我试图使用这个awk
命令来实现这一点,但它只处理了一些情况,用3*
替换所有单词,并将值切到最后3个字符(我对awk不是很好,所以也许它可以实现更好):
env | awk -F= '{ if(length($2)>5) {printf("%s=***%sn", $1, substr($2, length($2)-2))} }'
纯bash
的解决方案可能是:
#!/bin/bash
env |
while IFS='=' read -r name value; do
n=$((${#value} > 5 ? -3 : ${#value} > 0 ? -1 : 0))
head=${value:0:n}
printf '%s=%s%sn' "$name" "${head//?/'*'}" "${value:n}"
done
注意:在shell编程中,通过while read
循环读取行是低效的。我假设env
命令发出的输出足够小,这种低效率并不明显。对于大的输入,您不应该使用此技术。
用awk gensub:
试试这个脚本#!/bin/bash
env | awk -F= '{
name=$1;
value=$2;
if (length(value) > 5) {
mask=gensub(/./,"*","g",substr(value,1,length(value)-3));
value=mask substr(value,length(value)-2);
} else {
mask=gensub(/./,"*","g",substr(value,1,length(value)-1));
value=mask substr(value,length(value));
}
print name "=" value;
}'
如果您想偷懒,不关心星号的正确数量,您可以这样做:
$ env | sed 's/=(...*)(...)/=***2/'
如果星号必须是正确的总数,则可以使用awk。但是,使用等号作为字段分隔符并不是正确的方法,因为单行可能包含多个等号:
$ env | awk '{i=index($0,"="); s=substr($0,i+1);l=length(s)}(l>5){x=substr(s,1,l-3); gsub(/./,"*",x); print substr($0,1,i) s1 substr(s,l-2); next}1'
这里是一个稍微紧凑的awk
版本,它处理大于5个字符的环境字符串,将值中除最后三个字符外的所有字符替换为'*'
。在字符串少于5个字符的情况下,除最后一个字符外的所有字符都被替换。这与您的示例输出相匹配,尽管您没有提供包含4或5个字符的示例。
基本上awk
脚本构建一个"***"
字符正确数目的mask
和一个"..."
的带有替换字符数目的动态正则表达式re
,并调用sub()
进行替换,例如
awk -F= '
{
l = length($2)
mask = ""
re = ""
for (i=0;i<(l>5?l-3:l-1);i++) {
mask = mask "*"
re = re "."
}
mask = "=" mask
re = "=" re
sub (re, mask)
print
}' file
使用/输出示例
$ awk -F= '
> {
> l = length($2)
> mask = ""
> re = ""
> for (i=0;i<(l>5?l-3:l-1);i++) {
> mask = mask "*"
> re = re "."
> }
> mask = "=" mask
> re = "=" re
> sub (re, mask)
> print
> }' << eof
> FOO=qwerty
> BAR=asdfghjkl
> BAZ=zxc
> eof
FOO=***rty
BAR=******jkl
BAZ=**c
此方法预先生成"*" x 2,400
字符串,并通过substr()
-ing代替regex
,因此除非您的数据值超过2,400
字节/字符,否则这应该足够了。
mawk 'BEGIN { FS = OFS = "="; _=(_=(_="*")_ _)_
gsub(__,_,_) gsub(__,_,_); _ +=(_^= ___ = _)+_ }
$NF = sprintf("%.*s%s",__ -=_^((_+_) <= (__ = length($NF))), ___, substr($NF, ++__))'
FOO=***rty
BAR=******jkl
BAZ=**c