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 **cdevà *********jkl.
Nếu bạn thích, bạn cũng có thể sửa đổi ncá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-> ***devà 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 $RANDOMbiế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 zshbiế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, evalbạn có thể thực hiện với một vài điều printfsau:
# 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}evalcó 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 notcho các tìm kiếm giống như regexTrong khi tôi nhận được rằng
printflà 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