Echo with obfuscation
I need to print some variables to the screen but I need to preferebly obfuscate the first few characters and I was wondering if there was an echo command in bash that can obfuscate the first characters of a secret value while printing it to the terminal:
echo 'secretvalue'
********lue
bash security
New contributor
add a comment |
I need to print some variables to the screen but I need to preferebly obfuscate the first few characters and I was wondering if there was an echo command in bash that can obfuscate the first characters of a secret value while printing it to the terminal:
echo 'secretvalue'
********lue
bash security
New contributor
add a comment |
I need to print some variables to the screen but I need to preferebly obfuscate the first few characters and I was wondering if there was an echo command in bash that can obfuscate the first characters of a secret value while printing it to the terminal:
echo 'secretvalue'
********lue
bash security
New contributor
I need to print some variables to the screen but I need to preferebly obfuscate the first few characters and I was wondering if there was an echo command in bash that can obfuscate the first characters of a secret value while printing it to the terminal:
echo 'secretvalue'
********lue
bash security
bash security
New contributor
New contributor
edited yesterday
Jeff Schaller
43.8k1161141
43.8k1161141
New contributor
asked yesterday
XerxesXerxes
1735
1735
New contributor
New contributor
add a comment |
add a comment |
6 Answers
6
active
oldest
votes
The other answers mask a fixed amount of characters from the start, with the plaintext suffix varying in length. An alternative would be to leave a fixed amount of characters in plaintext, and to vary the length of the masked part. I don't know which one is more useful, but here's the other choice:
#!/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%sn" "${a//?/*}" "$b" # substitute a with asterisks
}
mask abcde
mask abcdefghijkl
This prints **cde
and *********jkl
.
If you like, you could also modify n
for short strings to make sure a majority of the string gets masked. E.g. this would make sure at least three characters are masked even for short strings. (so abcde
-> ***de
, and abc
-> ***
):
mask() {
local n=3
[[ ${#1} -le 5 ]] && n=$(( ${#1} - 3 ))
local a="${1:0:${#1}-n}"
local b="${1:${#1}-n}"
printf "%s%sn" "${a//?/*}" "$b"
}
add a comment |
One option would be to force yourself to use a function instead of echo
, such as:
obfuprint() {
if [ "${#1}" -ge 8 ]
then
printf '%sn' "${1/????????/********}"
else
printf '%sn' "${1//?/*}"
fi
}
Then you could call obfuprint 'secretvalue'
and receive ********lue
(with a trailing newline). The function uses parameter expansion to search for the first eight characters of the passed-in value and replaces them with eight asterisks. If the incoming value is shorter than eight characters, they are all replaced with asterisks. Thanks to ilkkachu for pointing out my initial assumption of eight-or-more character inputs!
Inspired by ilkkachu's flexible masking answer, I thought it'd be interesting to add a variation that randomly masks some percentage of the string:
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
}
This relies on bash's $RANDOM
special variable; it simply loops through each character of the input and decides whether to mask that character or print it. Sample output:
$ obfuprintperc 0123456789
0*****6*8*
$ obfuprintperc 0123456789
012***678*
$ obfuprintperc 0123456789
**********
$ obfuprintperc 0123456789
*****56***
$ obfuprintperc 0123456789
0*******8*
To be frank, I do not like random masking. A determined shoulder surfer will eventually get my secrets by pretending to like making small talk with me.
– emory
yesterday
Certainly, displaying sensitive information should be done carefully! I presented random masking as an alternative to fixed-prefix masking and variable-prefix masking.
– Jeff Schaller
yesterday
4
I am not a fan of fixed-prefix or variable-prefix masking either, but with those there exists a "kernel" of my secret that remains secret. With random masking, there is no "kernel". Eventually everything will be revealed to those patient enough.
– emory
yesterday
add a comment |
You could try piping to sed
. For example, to replace the first 8 characters of a string with asterisks, you could pipe to the sed 's/^......../********/'
command, e.g.:
$ echo 'secretvalue' | sed 's/^......../********/'
********lue
You can also define a function that does this:
obsecho () { echo "$1" | sed 's/^......../*********/'; }
2
I'd suggestprintf
overecho
so that you're not subject to interpreting data such asr
orn
– Jeff Schaller
yesterday
@JeffSchaller This is one of the reasons why I post on SE. Good point. Thanks for the feedback.
– igal
yesterday
It's one of the many things I've learned in my time here, as well! Happy to pass it along!
– Jeff Schaller
yesterday
1
No need to use a pipe when you can use a herestring instead:sed 's/^......../********/' <<< 'secretvalue'
– wjandrea
yesterday
@roaima It's actually a temporary regular file. You can see it if you dobash -c 'lsof -d0 -a -p $$ 2>/dev/null' <<< foo
.
– JoL
yesterday
|
show 1 more comment
A zsh
variant that masks three quarters of the text:
mask() printf '%sn' ${(l:$#1::*:)1:$#1*3/4}
Example:
$ mask secretvalue
********lue
$ mask 12345678
******78
$ mask 1234
***4
To mask the first 8 chars:
mask() printf '%sn' ${(l:$#1::*:)1:8}
To mask all but the last 3 chars:
mask() printf '%sn' ${(l:$#1::*:)1: -3}
To mask a random number of characters:
mask() printf '%sn' ${(l:$#1::*:)1: RANDOM%$#1}
add a comment |
Another option in Bash, if you don’t mind one simple eval you can do it with a couple of printf:
# example data
password=secretvalue
chars_to_show=3
# the real thing
eval "printf '*%.0s' {1..$((${#password} - chars_to_show))}"
printf '%sn' ${password: -chars_to_show}
But be careful:
- fix the above as you need when
${#password}
is less than${chars_to_show}
- eval can be very dangerous with untrusted input: here it can be considered safe because its input comes only from safe sources, ie the length of
${password}
and the value of${chars_to_show}
New contributor
add a comment |
Here's some toy Bash scripts to play with that show how to combine regex-like search with string substitution.
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
Key takeaways
[a-z 0-9]
is totally valid, and handy, as a<search>
within${_var_name//<search>/<replace>}
for Bash
^
, within this context, is the reverse ornot
for regex-like searches- Built-ins are generally faster and often are more concise, especially when it cuts out unneeded piping
While I get that
printf
is better in nearly all use cases the above code usesecho
so as to not overly confuse what's going on.
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
add a comment |
Your Answer
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "106"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Xerxes is a new contributor. Be nice, and check out our Code of Conduct.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f507450%2fecho-with-obfuscation%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
6 Answers
6
active
oldest
votes
6 Answers
6
active
oldest
votes
active
oldest
votes
active
oldest
votes
The other answers mask a fixed amount of characters from the start, with the plaintext suffix varying in length. An alternative would be to leave a fixed amount of characters in plaintext, and to vary the length of the masked part. I don't know which one is more useful, but here's the other choice:
#!/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%sn" "${a//?/*}" "$b" # substitute a with asterisks
}
mask abcde
mask abcdefghijkl
This prints **cde
and *********jkl
.
If you like, you could also modify n
for short strings to make sure a majority of the string gets masked. E.g. this would make sure at least three characters are masked even for short strings. (so abcde
-> ***de
, and abc
-> ***
):
mask() {
local n=3
[[ ${#1} -le 5 ]] && n=$(( ${#1} - 3 ))
local a="${1:0:${#1}-n}"
local b="${1:${#1}-n}"
printf "%s%sn" "${a//?/*}" "$b"
}
add a comment |
The other answers mask a fixed amount of characters from the start, with the plaintext suffix varying in length. An alternative would be to leave a fixed amount of characters in plaintext, and to vary the length of the masked part. I don't know which one is more useful, but here's the other choice:
#!/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%sn" "${a//?/*}" "$b" # substitute a with asterisks
}
mask abcde
mask abcdefghijkl
This prints **cde
and *********jkl
.
If you like, you could also modify n
for short strings to make sure a majority of the string gets masked. E.g. this would make sure at least three characters are masked even for short strings. (so abcde
-> ***de
, and abc
-> ***
):
mask() {
local n=3
[[ ${#1} -le 5 ]] && n=$(( ${#1} - 3 ))
local a="${1:0:${#1}-n}"
local b="${1:${#1}-n}"
printf "%s%sn" "${a//?/*}" "$b"
}
add a comment |
The other answers mask a fixed amount of characters from the start, with the plaintext suffix varying in length. An alternative would be to leave a fixed amount of characters in plaintext, and to vary the length of the masked part. I don't know which one is more useful, but here's the other choice:
#!/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%sn" "${a//?/*}" "$b" # substitute a with asterisks
}
mask abcde
mask abcdefghijkl
This prints **cde
and *********jkl
.
If you like, you could also modify n
for short strings to make sure a majority of the string gets masked. E.g. this would make sure at least three characters are masked even for short strings. (so abcde
-> ***de
, and abc
-> ***
):
mask() {
local n=3
[[ ${#1} -le 5 ]] && n=$(( ${#1} - 3 ))
local a="${1:0:${#1}-n}"
local b="${1:${#1}-n}"
printf "%s%sn" "${a//?/*}" "$b"
}
The other answers mask a fixed amount of characters from the start, with the plaintext suffix varying in length. An alternative would be to leave a fixed amount of characters in plaintext, and to vary the length of the masked part. I don't know which one is more useful, but here's the other choice:
#!/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%sn" "${a//?/*}" "$b" # substitute a with asterisks
}
mask abcde
mask abcdefghijkl
This prints **cde
and *********jkl
.
If you like, you could also modify n
for short strings to make sure a majority of the string gets masked. E.g. this would make sure at least three characters are masked even for short strings. (so abcde
-> ***de
, and abc
-> ***
):
mask() {
local n=3
[[ ${#1} -le 5 ]] && n=$(( ${#1} - 3 ))
local a="${1:0:${#1}-n}"
local b="${1:${#1}-n}"
printf "%s%sn" "${a//?/*}" "$b"
}
edited yesterday
answered yesterday
ilkkachuilkkachu
62.1k10103179
62.1k10103179
add a comment |
add a comment |
One option would be to force yourself to use a function instead of echo
, such as:
obfuprint() {
if [ "${#1}" -ge 8 ]
then
printf '%sn' "${1/????????/********}"
else
printf '%sn' "${1//?/*}"
fi
}
Then you could call obfuprint 'secretvalue'
and receive ********lue
(with a trailing newline). The function uses parameter expansion to search for the first eight characters of the passed-in value and replaces them with eight asterisks. If the incoming value is shorter than eight characters, they are all replaced with asterisks. Thanks to ilkkachu for pointing out my initial assumption of eight-or-more character inputs!
Inspired by ilkkachu's flexible masking answer, I thought it'd be interesting to add a variation that randomly masks some percentage of the string:
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
}
This relies on bash's $RANDOM
special variable; it simply loops through each character of the input and decides whether to mask that character or print it. Sample output:
$ obfuprintperc 0123456789
0*****6*8*
$ obfuprintperc 0123456789
012***678*
$ obfuprintperc 0123456789
**********
$ obfuprintperc 0123456789
*****56***
$ obfuprintperc 0123456789
0*******8*
To be frank, I do not like random masking. A determined shoulder surfer will eventually get my secrets by pretending to like making small talk with me.
– emory
yesterday
Certainly, displaying sensitive information should be done carefully! I presented random masking as an alternative to fixed-prefix masking and variable-prefix masking.
– Jeff Schaller
yesterday
4
I am not a fan of fixed-prefix or variable-prefix masking either, but with those there exists a "kernel" of my secret that remains secret. With random masking, there is no "kernel". Eventually everything will be revealed to those patient enough.
– emory
yesterday
add a comment |
One option would be to force yourself to use a function instead of echo
, such as:
obfuprint() {
if [ "${#1}" -ge 8 ]
then
printf '%sn' "${1/????????/********}"
else
printf '%sn' "${1//?/*}"
fi
}
Then you could call obfuprint 'secretvalue'
and receive ********lue
(with a trailing newline). The function uses parameter expansion to search for the first eight characters of the passed-in value and replaces them with eight asterisks. If the incoming value is shorter than eight characters, they are all replaced with asterisks. Thanks to ilkkachu for pointing out my initial assumption of eight-or-more character inputs!
Inspired by ilkkachu's flexible masking answer, I thought it'd be interesting to add a variation that randomly masks some percentage of the string:
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
}
This relies on bash's $RANDOM
special variable; it simply loops through each character of the input and decides whether to mask that character or print it. Sample output:
$ obfuprintperc 0123456789
0*****6*8*
$ obfuprintperc 0123456789
012***678*
$ obfuprintperc 0123456789
**********
$ obfuprintperc 0123456789
*****56***
$ obfuprintperc 0123456789
0*******8*
To be frank, I do not like random masking. A determined shoulder surfer will eventually get my secrets by pretending to like making small talk with me.
– emory
yesterday
Certainly, displaying sensitive information should be done carefully! I presented random masking as an alternative to fixed-prefix masking and variable-prefix masking.
– Jeff Schaller
yesterday
4
I am not a fan of fixed-prefix or variable-prefix masking either, but with those there exists a "kernel" of my secret that remains secret. With random masking, there is no "kernel". Eventually everything will be revealed to those patient enough.
– emory
yesterday
add a comment |
One option would be to force yourself to use a function instead of echo
, such as:
obfuprint() {
if [ "${#1}" -ge 8 ]
then
printf '%sn' "${1/????????/********}"
else
printf '%sn' "${1//?/*}"
fi
}
Then you could call obfuprint 'secretvalue'
and receive ********lue
(with a trailing newline). The function uses parameter expansion to search for the first eight characters of the passed-in value and replaces them with eight asterisks. If the incoming value is shorter than eight characters, they are all replaced with asterisks. Thanks to ilkkachu for pointing out my initial assumption of eight-or-more character inputs!
Inspired by ilkkachu's flexible masking answer, I thought it'd be interesting to add a variation that randomly masks some percentage of the string:
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
}
This relies on bash's $RANDOM
special variable; it simply loops through each character of the input and decides whether to mask that character or print it. Sample output:
$ obfuprintperc 0123456789
0*****6*8*
$ obfuprintperc 0123456789
012***678*
$ obfuprintperc 0123456789
**********
$ obfuprintperc 0123456789
*****56***
$ obfuprintperc 0123456789
0*******8*
One option would be to force yourself to use a function instead of echo
, such as:
obfuprint() {
if [ "${#1}" -ge 8 ]
then
printf '%sn' "${1/????????/********}"
else
printf '%sn' "${1//?/*}"
fi
}
Then you could call obfuprint 'secretvalue'
and receive ********lue
(with a trailing newline). The function uses parameter expansion to search for the first eight characters of the passed-in value and replaces them with eight asterisks. If the incoming value is shorter than eight characters, they are all replaced with asterisks. Thanks to ilkkachu for pointing out my initial assumption of eight-or-more character inputs!
Inspired by ilkkachu's flexible masking answer, I thought it'd be interesting to add a variation that randomly masks some percentage of the string:
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
}
This relies on bash's $RANDOM
special variable; it simply loops through each character of the input and decides whether to mask that character or print it. Sample output:
$ obfuprintperc 0123456789
0*****6*8*
$ obfuprintperc 0123456789
012***678*
$ obfuprintperc 0123456789
**********
$ obfuprintperc 0123456789
*****56***
$ obfuprintperc 0123456789
0*******8*
edited yesterday
answered yesterday
Jeff SchallerJeff Schaller
43.8k1161141
43.8k1161141
To be frank, I do not like random masking. A determined shoulder surfer will eventually get my secrets by pretending to like making small talk with me.
– emory
yesterday
Certainly, displaying sensitive information should be done carefully! I presented random masking as an alternative to fixed-prefix masking and variable-prefix masking.
– Jeff Schaller
yesterday
4
I am not a fan of fixed-prefix or variable-prefix masking either, but with those there exists a "kernel" of my secret that remains secret. With random masking, there is no "kernel". Eventually everything will be revealed to those patient enough.
– emory
yesterday
add a comment |
To be frank, I do not like random masking. A determined shoulder surfer will eventually get my secrets by pretending to like making small talk with me.
– emory
yesterday
Certainly, displaying sensitive information should be done carefully! I presented random masking as an alternative to fixed-prefix masking and variable-prefix masking.
– Jeff Schaller
yesterday
4
I am not a fan of fixed-prefix or variable-prefix masking either, but with those there exists a "kernel" of my secret that remains secret. With random masking, there is no "kernel". Eventually everything will be revealed to those patient enough.
– emory
yesterday
To be frank, I do not like random masking. A determined shoulder surfer will eventually get my secrets by pretending to like making small talk with me.
– emory
yesterday
To be frank, I do not like random masking. A determined shoulder surfer will eventually get my secrets by pretending to like making small talk with me.
– emory
yesterday
Certainly, displaying sensitive information should be done carefully! I presented random masking as an alternative to fixed-prefix masking and variable-prefix masking.
– Jeff Schaller
yesterday
Certainly, displaying sensitive information should be done carefully! I presented random masking as an alternative to fixed-prefix masking and variable-prefix masking.
– Jeff Schaller
yesterday
4
4
I am not a fan of fixed-prefix or variable-prefix masking either, but with those there exists a "kernel" of my secret that remains secret. With random masking, there is no "kernel". Eventually everything will be revealed to those patient enough.
– emory
yesterday
I am not a fan of fixed-prefix or variable-prefix masking either, but with those there exists a "kernel" of my secret that remains secret. With random masking, there is no "kernel". Eventually everything will be revealed to those patient enough.
– emory
yesterday
add a comment |
You could try piping to sed
. For example, to replace the first 8 characters of a string with asterisks, you could pipe to the sed 's/^......../********/'
command, e.g.:
$ echo 'secretvalue' | sed 's/^......../********/'
********lue
You can also define a function that does this:
obsecho () { echo "$1" | sed 's/^......../*********/'; }
2
I'd suggestprintf
overecho
so that you're not subject to interpreting data such asr
orn
– Jeff Schaller
yesterday
@JeffSchaller This is one of the reasons why I post on SE. Good point. Thanks for the feedback.
– igal
yesterday
It's one of the many things I've learned in my time here, as well! Happy to pass it along!
– Jeff Schaller
yesterday
1
No need to use a pipe when you can use a herestring instead:sed 's/^......../********/' <<< 'secretvalue'
– wjandrea
yesterday
@roaima It's actually a temporary regular file. You can see it if you dobash -c 'lsof -d0 -a -p $$ 2>/dev/null' <<< foo
.
– JoL
yesterday
|
show 1 more comment
You could try piping to sed
. For example, to replace the first 8 characters of a string with asterisks, you could pipe to the sed 's/^......../********/'
command, e.g.:
$ echo 'secretvalue' | sed 's/^......../********/'
********lue
You can also define a function that does this:
obsecho () { echo "$1" | sed 's/^......../*********/'; }
2
I'd suggestprintf
overecho
so that you're not subject to interpreting data such asr
orn
– Jeff Schaller
yesterday
@JeffSchaller This is one of the reasons why I post on SE. Good point. Thanks for the feedback.
– igal
yesterday
It's one of the many things I've learned in my time here, as well! Happy to pass it along!
– Jeff Schaller
yesterday
1
No need to use a pipe when you can use a herestring instead:sed 's/^......../********/' <<< 'secretvalue'
– wjandrea
yesterday
@roaima It's actually a temporary regular file. You can see it if you dobash -c 'lsof -d0 -a -p $$ 2>/dev/null' <<< foo
.
– JoL
yesterday
|
show 1 more comment
You could try piping to sed
. For example, to replace the first 8 characters of a string with asterisks, you could pipe to the sed 's/^......../********/'
command, e.g.:
$ echo 'secretvalue' | sed 's/^......../********/'
********lue
You can also define a function that does this:
obsecho () { echo "$1" | sed 's/^......../*********/'; }
You could try piping to sed
. For example, to replace the first 8 characters of a string with asterisks, you could pipe to the sed 's/^......../********/'
command, e.g.:
$ echo 'secretvalue' | sed 's/^......../********/'
********lue
You can also define a function that does this:
obsecho () { echo "$1" | sed 's/^......../*********/'; }
answered yesterday
igaligal
5,9611536
5,9611536
2
I'd suggestprintf
overecho
so that you're not subject to interpreting data such asr
orn
– Jeff Schaller
yesterday
@JeffSchaller This is one of the reasons why I post on SE. Good point. Thanks for the feedback.
– igal
yesterday
It's one of the many things I've learned in my time here, as well! Happy to pass it along!
– Jeff Schaller
yesterday
1
No need to use a pipe when you can use a herestring instead:sed 's/^......../********/' <<< 'secretvalue'
– wjandrea
yesterday
@roaima It's actually a temporary regular file. You can see it if you dobash -c 'lsof -d0 -a -p $$ 2>/dev/null' <<< foo
.
– JoL
yesterday
|
show 1 more comment
2
I'd suggestprintf
overecho
so that you're not subject to interpreting data such asr
orn
– Jeff Schaller
yesterday
@JeffSchaller This is one of the reasons why I post on SE. Good point. Thanks for the feedback.
– igal
yesterday
It's one of the many things I've learned in my time here, as well! Happy to pass it along!
– Jeff Schaller
yesterday
1
No need to use a pipe when you can use a herestring instead:sed 's/^......../********/' <<< 'secretvalue'
– wjandrea
yesterday
@roaima It's actually a temporary regular file. You can see it if you dobash -c 'lsof -d0 -a -p $$ 2>/dev/null' <<< foo
.
– JoL
yesterday
2
2
I'd suggest
printf
over echo
so that you're not subject to interpreting data such as r
or n
– Jeff Schaller
yesterday
I'd suggest
printf
over echo
so that you're not subject to interpreting data such as r
or n
– Jeff Schaller
yesterday
@JeffSchaller This is one of the reasons why I post on SE. Good point. Thanks for the feedback.
– igal
yesterday
@JeffSchaller This is one of the reasons why I post on SE. Good point. Thanks for the feedback.
– igal
yesterday
It's one of the many things I've learned in my time here, as well! Happy to pass it along!
– Jeff Schaller
yesterday
It's one of the many things I've learned in my time here, as well! Happy to pass it along!
– Jeff Schaller
yesterday
1
1
No need to use a pipe when you can use a herestring instead:
sed 's/^......../********/' <<< 'secretvalue'
– wjandrea
yesterday
No need to use a pipe when you can use a herestring instead:
sed 's/^......../********/' <<< 'secretvalue'
– wjandrea
yesterday
@roaima It's actually a temporary regular file. You can see it if you do
bash -c 'lsof -d0 -a -p $$ 2>/dev/null' <<< foo
.– JoL
yesterday
@roaima It's actually a temporary regular file. You can see it if you do
bash -c 'lsof -d0 -a -p $$ 2>/dev/null' <<< foo
.– JoL
yesterday
|
show 1 more comment
A zsh
variant that masks three quarters of the text:
mask() printf '%sn' ${(l:$#1::*:)1:$#1*3/4}
Example:
$ mask secretvalue
********lue
$ mask 12345678
******78
$ mask 1234
***4
To mask the first 8 chars:
mask() printf '%sn' ${(l:$#1::*:)1:8}
To mask all but the last 3 chars:
mask() printf '%sn' ${(l:$#1::*:)1: -3}
To mask a random number of characters:
mask() printf '%sn' ${(l:$#1::*:)1: RANDOM%$#1}
add a comment |
A zsh
variant that masks three quarters of the text:
mask() printf '%sn' ${(l:$#1::*:)1:$#1*3/4}
Example:
$ mask secretvalue
********lue
$ mask 12345678
******78
$ mask 1234
***4
To mask the first 8 chars:
mask() printf '%sn' ${(l:$#1::*:)1:8}
To mask all but the last 3 chars:
mask() printf '%sn' ${(l:$#1::*:)1: -3}
To mask a random number of characters:
mask() printf '%sn' ${(l:$#1::*:)1: RANDOM%$#1}
add a comment |
A zsh
variant that masks three quarters of the text:
mask() printf '%sn' ${(l:$#1::*:)1:$#1*3/4}
Example:
$ mask secretvalue
********lue
$ mask 12345678
******78
$ mask 1234
***4
To mask the first 8 chars:
mask() printf '%sn' ${(l:$#1::*:)1:8}
To mask all but the last 3 chars:
mask() printf '%sn' ${(l:$#1::*:)1: -3}
To mask a random number of characters:
mask() printf '%sn' ${(l:$#1::*:)1: RANDOM%$#1}
A zsh
variant that masks three quarters of the text:
mask() printf '%sn' ${(l:$#1::*:)1:$#1*3/4}
Example:
$ mask secretvalue
********lue
$ mask 12345678
******78
$ mask 1234
***4
To mask the first 8 chars:
mask() printf '%sn' ${(l:$#1::*:)1:8}
To mask all but the last 3 chars:
mask() printf '%sn' ${(l:$#1::*:)1: -3}
To mask a random number of characters:
mask() printf '%sn' ${(l:$#1::*:)1: RANDOM%$#1}
edited 10 hours ago
answered yesterday
Stéphane ChazelasStéphane Chazelas
311k57586945
311k57586945
add a comment |
add a comment |
Another option in Bash, if you don’t mind one simple eval you can do it with a couple of printf:
# example data
password=secretvalue
chars_to_show=3
# the real thing
eval "printf '*%.0s' {1..$((${#password} - chars_to_show))}"
printf '%sn' ${password: -chars_to_show}
But be careful:
- fix the above as you need when
${#password}
is less than${chars_to_show}
- eval can be very dangerous with untrusted input: here it can be considered safe because its input comes only from safe sources, ie the length of
${password}
and the value of${chars_to_show}
New contributor
add a comment |
Another option in Bash, if you don’t mind one simple eval you can do it with a couple of printf:
# example data
password=secretvalue
chars_to_show=3
# the real thing
eval "printf '*%.0s' {1..$((${#password} - chars_to_show))}"
printf '%sn' ${password: -chars_to_show}
But be careful:
- fix the above as you need when
${#password}
is less than${chars_to_show}
- eval can be very dangerous with untrusted input: here it can be considered safe because its input comes only from safe sources, ie the length of
${password}
and the value of${chars_to_show}
New contributor
add a comment |
Another option in Bash, if you don’t mind one simple eval you can do it with a couple of printf:
# example data
password=secretvalue
chars_to_show=3
# the real thing
eval "printf '*%.0s' {1..$((${#password} - chars_to_show))}"
printf '%sn' ${password: -chars_to_show}
But be careful:
- fix the above as you need when
${#password}
is less than${chars_to_show}
- eval can be very dangerous with untrusted input: here it can be considered safe because its input comes only from safe sources, ie the length of
${password}
and the value of${chars_to_show}
New contributor
Another option in Bash, if you don’t mind one simple eval you can do it with a couple of printf:
# example data
password=secretvalue
chars_to_show=3
# the real thing
eval "printf '*%.0s' {1..$((${#password} - chars_to_show))}"
printf '%sn' ${password: -chars_to_show}
But be careful:
- fix the above as you need when
${#password}
is less than${chars_to_show}
- eval can be very dangerous with untrusted input: here it can be considered safe because its input comes only from safe sources, ie the length of
${password}
and the value of${chars_to_show}
New contributor
edited 14 hours ago
ilkkachu
62.1k10103179
62.1k10103179
New contributor
answered yesterday
LL3LL3
863
863
New contributor
New contributor
add a comment |
add a comment |
Here's some toy Bash scripts to play with that show how to combine regex-like search with string substitution.
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
Key takeaways
[a-z 0-9]
is totally valid, and handy, as a<search>
within${_var_name//<search>/<replace>}
for Bash
^
, within this context, is the reverse ornot
for regex-like searches- Built-ins are generally faster and often are more concise, especially when it cuts out unneeded piping
While I get that
printf
is better in nearly all use cases the above code usesecho
so as to not overly confuse what's going on.
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
add a comment |
Here's some toy Bash scripts to play with that show how to combine regex-like search with string substitution.
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
Key takeaways
[a-z 0-9]
is totally valid, and handy, as a<search>
within${_var_name//<search>/<replace>}
for Bash
^
, within this context, is the reverse ornot
for regex-like searches- Built-ins are generally faster and often are more concise, especially when it cuts out unneeded piping
While I get that
printf
is better in nearly all use cases the above code usesecho
so as to not overly confuse what's going on.
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
add a comment |
Here's some toy Bash scripts to play with that show how to combine regex-like search with string substitution.
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
Key takeaways
[a-z 0-9]
is totally valid, and handy, as a<search>
within${_var_name//<search>/<replace>}
for Bash
^
, within this context, is the reverse ornot
for regex-like searches- Built-ins are generally faster and often are more concise, especially when it cuts out unneeded piping
While I get that
printf
is better in nearly all use cases the above code usesecho
so as to not overly confuse what's going on.
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
Here's some toy Bash scripts to play with that show how to combine regex-like search with string substitution.
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
Key takeaways
[a-z 0-9]
is totally valid, and handy, as a<search>
within${_var_name//<search>/<replace>}
for Bash
^
, within this context, is the reverse ornot
for regex-like searches- Built-ins are generally faster and often are more concise, especially when it cuts out unneeded piping
While I get that
printf
is better in nearly all use cases the above code usesecho
so as to not overly confuse what's going on.
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
edited 1 hour ago
answered 1 hour ago
S0AndS0S0AndS0
1867
1867
add a comment |
add a comment |
Xerxes is a new contributor. Be nice, and check out our Code of Conduct.
Xerxes is a new contributor. Be nice, and check out our Code of Conduct.
Xerxes is a new contributor. Be nice, and check out our Code of Conduct.
Xerxes is a new contributor. Be nice, and check out our Code of Conduct.
Thanks for contributing an answer to Unix & Linux Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f507450%2fecho-with-obfuscation%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown