Câu trả lời:
Các câu trả lời khác che giấu một số lượng ký tự cố định từ đầu, với hậu tố văn bản khác nhau về chiều dài. Một cách khác là để lại một lượng ký tự cố định trong văn bản gốc và thay đổi độ dài của phần bị che. Tôi không biết cái nào hữu ích hơn, nhưng đây là lựa chọn khác:
#!/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
Điều này in **cde
và *********jkl
.
Nếu bạn thích, bạn cũng có thể sửa đổi n
các chuỗi ngắn để đảm bảo phần lớn chuỗi được che. Ví dụ, điều này sẽ đảm bảo ít nhất ba ký tự được che dấu ngay cả đối với các chuỗi ngắn. (vì vậy abcde
-> ***de
và 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"
}
Một lựa chọn sẽ là buộc bản thân sử dụng một chức năng thay vì echo
, chẳng hạn như:
obfuprint() {
if [ "${#1}" -ge 8 ]
then
printf '%s\n' "${1/????????/********}"
else
printf '%s\n' "${1//?/*}"
fi
}
Sau đó, bạn có thể gọi obfuprint 'secretvalue'
và nhận ********lue
(với một dòng mới). Hàm sử dụng mở rộng tham số để tìm kiếm tám ký tự đầu tiên của giá trị được truyền vào và thay thế chúng bằng tám dấu sao. Nếu giá trị đến ngắn hơn tám ký tự, tất cả chúng đều được thay thế bằng dấu hoa thị. Cảm ơn ilkkachu đã chỉ ra giả định ban đầu của tôi về đầu vào tám ký tự trở lên!
Lấy cảm hứng từ câu trả lời mặt nạ linh hoạt của ilkkachu , tôi nghĩ thật thú vị khi thêm một biến thể che dấu ngẫu nhiên một số phần trăm của chuỗi:
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
}
Điều này phụ thuộc vào $RANDOM
biến đặc biệt của bash ; nó chỉ đơn giản là lặp qua từng ký tự của đầu vào và quyết định xem có che dấu ký tự đó hay in nó không. Đầu ra mẫu:
$ obfuprintperc 0123456789
0*****6*8*
$ obfuprintperc 0123456789
012***678*
$ obfuprintperc 0123456789
**********
$ obfuprintperc 0123456789
*****56***
$ obfuprintperc 0123456789
0*******8*
Bạn có thể thử đường ống đến sed
. Ví dụ: để thay thế 8 ký tự đầu tiên của chuỗi bằng dấu hoa thị, bạn có thể chuyển sang sed 's/^......../********/'
lệnh, ví dụ:
$ echo 'secretvalue' | sed 's/^......../********/'
********lue
Bạn cũng có thể định nghĩa một hàm thực hiện điều này:
obsecho () { echo "$1" | sed 's/^......../*********/'; }
sed 's/^......../********/' <<< 'secretvalue'
bash -c 'lsof -d0 -a -p $$ 2>/dev/null' <<< foo
.
Một zsh
biến thể che dấu ba phần tư của văn bản:
mask() printf '%s\n' ${(l:$#1::*:)1:$#1*3/4}
Thí dụ:
$ mask secretvalue
********lue
$ mask 12345678
******78
$ mask 1234
***4
Để che dấu 8 ký tự đầu tiên:
mask() printf '%s\n' ${(l:$#1::*:)1:8}
Để che dấu tất cả trừ 3 ký tự cuối cùng:
mask() printf '%s\n' ${(l:$#1::*:)1: -3}
Để che dấu một số ký tự ngẫu nhiên:
mask() printf '%s\n' ${(l:$#1::*:)1: RANDOM%$#1}
Một tùy chọn khác trong Bash, nếu bạn không phiền một cách đơn giản, eval
bạn có thể thực hiện với một vài điều printf
sau:
# 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}"
Nhưng hãy cẩn thận:
${#password}
ít hơn${chars_to_show}
eval
có thể rất nguy hiểm với đầu vào không đáng tin cậy: ở đây có thể được coi là an toàn vì đầu vào của nó chỉ đến từ các nguồn an toàn, tức là độ dài ${password}
và giá trị của${chars_to_show}
Đây là một số kịch bản Bash đồ chơi để chơi với nó cho thấy cách kết hợp tìm kiếm giống như biểu thức chính quy với thay thế chuỗi.
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
Chìa khóa chính
[a-z 0-9]
là hoàn toàn hợp lệ và tiện dụng, như một phần <search>
trong ${_var_name//<search>/<replace>}
Bash^
, trong bối cảnh này, là đảo ngược hoặc not
cho các tìm kiếm giống như regexTrong khi tôi nhận được rằng
printf
là tốt hơn trong hầu hết các trường hợp sử dụng những ứng dụng mã trênecho
để không quá nhầm lẫn giữa những gì đang xảy ra.
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