Answers:
其他答案从一开始就掩盖了固定数量的字符,明文后缀的长度有所不同。另一种选择是在明文中保留固定数量的字符,并更改被遮罩部分的长度。我不知道哪个更有用,但这是另一个选择:
#!/bin/bash
mask() {
local n=3 # number of chars to leave
local a="${1:0:${#1}-n}" # take all but the last n chars
local b="${1:${#1}-n}" # take the final n chars
printf "%s%s\n" "${a//?/*}" "$b" # substitute a with asterisks
}
mask abcde
mask abcdefghijkl
打印**cde
和*********jkl
。
如果愿意,还可以修改n
短字符串,以确保大部分字符串被屏蔽。例如,这将确保即使是短字符串也至少要屏蔽三个字符。(因此abcde
-> ***de
和abc
-> ***
):
mask() {
local n=3
[[ ${#1} -le 5 ]] && n=$(( ${#1} - 3 ))
local a="${1:0:${#1}-n}"
local b="${1:${#1}-n}"
printf "%s%s\n" "${a//?/*}" "$b"
}
一种选择是强制您自己使用函数而不是echo
,例如:
obfuprint() {
if [ "${#1}" -ge 8 ]
then
printf '%s\n' "${1/????????/********}"
else
printf '%s\n' "${1//?/*}"
fi
}
然后,您可以拨打电话obfuprint 'secretvalue'
并接收********lue
(带有换行符)。该函数使用参数扩展来搜索传入值的前八个字符,并将其替换为八个星号。如果输入的值少于八个字符,则将它们全部替换为星号。感谢ilkkachu指出了我最初对八个或更多字符输入的假设!
受到ilkkachu灵活的屏蔽答案的启发,我认为添加一个随机屏蔽一部分字符串的变体会很有趣:
obfuprintperc () {
local perc=75 ## percent to obfuscate
local i=0
for((i=0; i < ${#1}; i++))
do
if [ $(( $RANDOM % 100 )) -lt "$perc" ]
then
printf '%s' '*'
else
printf '%s' "${1:i:1}"
fi
done
echo
}
这依赖于bash的$RANDOM
特殊变量。它只是循环遍历输入的每个字符,并决定是掩盖该字符还是打印该字符。样本输出:
$ obfuprintperc 0123456789
0*****6*8*
$ obfuprintperc 0123456789
012***678*
$ obfuprintperc 0123456789
**********
$ obfuprintperc 0123456789
*****56***
$ obfuprintperc 0123456789
0*******8*
您可以尝试管道连接到sed
。例如,要将字符串的前8个字符替换为星号,可以通过管道传递给sed 's/^......../********/'
命令,例如:
$ echo 'secretvalue' | sed 's/^......../********/'
********lue
您还可以定义执行此操作的函数:
obsecho () { echo "$1" | sed 's/^......../*********/'; }
sed 's/^......../********/' <<< 'secretvalue'
bash -c 'lsof -d0 -a -p $$ 2>/dev/null' <<< foo
。
一种zsh
变体,遮盖了文本的四分之三:
mask() printf '%s\n' ${(l:$#1::*:)1:$#1*3/4}
例:
$ mask secretvalue
********lue
$ mask 12345678
******78
$ mask 1234
***4
要屏蔽前8个字符:
mask() printf '%s\n' ${(l:$#1::*:)1:8}
要屏蔽除最后三个字符外的所有字符:
mask() printf '%s\n' ${(l:$#1::*:)1: -3}
要屏蔽任意数量的字符:
mask() printf '%s\n' ${(l:$#1::*:)1: RANDOM%$#1}
Bash的另一种选择,如果您不介意简单的eval
话,可以使用以下几种方法printf
:
# example data
password=secretvalue
chars_to_show=3
# the real thing
eval "printf '*%.0s' {1..$((${#password} - chars_to_show))}"
printf '%s\n' "${password: -chars_to_show}"
不过要小心:
${#password}
小于${chars_to_show}
eval
输入不受信任可能会非常危险:在这里可以将其视为安全的,因为其输入仅来自安全来源,即的长度${password}
和值${chars_to_show}
这是一些玩具 Bash脚本,用于演示如何将类似正则表达式的搜索与字符串替换结合在一起。
strip_str.sh
#!/usr/bin/env bash
_str="${1}"
_filter="${2:-'apl'}"
echo "${_str//[${_filter}]/}"
strip_str.sh 'apple-foo bar'
# -> e-foo br
strip_str.sh 'apple-foo bar' 'a'
# -> pple-foo br
privatize_str.sh
#!/usr/bin/env bash
_str="${1}"
_filter="${2:-'apl'}"
_replace="${3:-'*'}"
echo "${_str//[${_filter}]/${_replace}}"
privatize_str.sh 'apple-foo bar'
# -> ****e-foo b*r
restricted_str.sh
#!/usr/bin/env bash
_str="${1}"
_valid="${2:-'a-z'}"
_replace="${3:-''}"
echo "${_str//[^${_valid}]/${_replace}}"
restricted_str.sh 'apple-foo bar'
# -> applefoobar
重要要点
[a-z 0-9]
是完全有效的,方便的,作为<search>
内${_var_name//<search>/<replace>}
进行猛砸^
在这种情况下是反向not
搜索或正则表达式搜索虽然我得到的
printf
是更好地在几乎所有的用例上面的代码使用echo
,从而不会过度混淆发生了什么事情。
obfuscate_str.sh
#!/usr/bin/env bash
_str="${1}"
_start="${2:-6}"
_header="$(for i in {1..${_start}}; do echo -n '*'; done)"
echo "${_header}${_str:${_start}}"
obfuscate_str.sh 'apple-foo bar' 3
# -> ***le-foo bar