如何在Linux上打印带有掩码值的环境名称?

00jrzges  于 2023-01-25  发布在  Linux
关注(0)|答案(5)|浏览(101)

我想使用标准工具和bash打印Linux上的所有环境变量。如果变量长度大于5(qwerty-〉***rty),我需要看到环境名称和最后3个字符可见的掩码变量,如果变量长度小于5(或等于5)(zxc-〉**c),则掩码值为1个可见字符。
示例:

FOO=qwerty
BAR=asdfghjkl
BAZ=zxc

我期待这个命令打印出来:

FOO=***rty
BAR=******jkl
BAZ=**c

原始值和掩码的长度在这里是相同的。
目前我尝试使用这个awk命令来实现它,但它只处理了其中的一些情况,将所有word替换为3个*,并将值削减到最后3个字符(我不太擅长awk,所以也许可以更好地实现它):

env | awk -F= '{ if(length($2)>5) {printf("%s=***%s\n", $1, substr($2, length($2)-2))} }'
wlsrxk51

wlsrxk511#

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%s\n' "$name" "${head//?/'*'}" "${value:n}"
done

注意:在shell编程中,通过while read循环阅读行是低效的。我假设env命令发出的输出足够小,这种低效并不明显。你不应该对大输入使用这种技术。

yqyhoc1h

yqyhoc1h2#

使用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;
}'
gfttwv5a

gfttwv5a3#

如果你想偷懒,不在乎星号的正确数量,你可以这样做:

$ 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'
wmtdaxz3

wmtdaxz34#

这里是一个稍微更紧凑的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
ykejflvf

ykejflvf5#

这种方法预先生成了一个"*" 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

相关问题