How to allow only certain characters in a bash variable
I want to prompt the user to input a URL, but it can only contain A-Z
, a-z
, 0-9
, &
, .
, /
, =
, _
, -
, :
, and ?
.
So, for example:
Enter URL:
$ http://youtube.com/watch?v=1234df_AQ-x
That URL is allowed.
Enter URL:
$ https://unix.stackexchange.com/$FAKEurl%🍺123
That URL is NOT allowed.
This is what I've come up with so far, but it doesn't seem to work correctly:
if [[ ! "${URL}" == *[abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890-_/&?:.=]* ]]; then
echo "That URL is NOT allowed."
else
echo "That URL is allowed."
fi
Please note that the URLs I provided in the example are just examples.
This script needs to work with all possible user input; it just can't contain characters other than the ones I specified earlier.
Using bash 3.2.57(1)-release under macOS High Sierra 10.13.6.
bash text-processing osx variable
New contributor
add a comment |
I want to prompt the user to input a URL, but it can only contain A-Z
, a-z
, 0-9
, &
, .
, /
, =
, _
, -
, :
, and ?
.
So, for example:
Enter URL:
$ http://youtube.com/watch?v=1234df_AQ-x
That URL is allowed.
Enter URL:
$ https://unix.stackexchange.com/$FAKEurl%🍺123
That URL is NOT allowed.
This is what I've come up with so far, but it doesn't seem to work correctly:
if [[ ! "${URL}" == *[abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890-_/&?:.=]* ]]; then
echo "That URL is NOT allowed."
else
echo "That URL is allowed."
fi
Please note that the URLs I provided in the example are just examples.
This script needs to work with all possible user input; it just can't contain characters other than the ones I specified earlier.
Using bash 3.2.57(1)-release under macOS High Sierra 10.13.6.
bash text-processing osx variable
New contributor
add a comment |
I want to prompt the user to input a URL, but it can only contain A-Z
, a-z
, 0-9
, &
, .
, /
, =
, _
, -
, :
, and ?
.
So, for example:
Enter URL:
$ http://youtube.com/watch?v=1234df_AQ-x
That URL is allowed.
Enter URL:
$ https://unix.stackexchange.com/$FAKEurl%🍺123
That URL is NOT allowed.
This is what I've come up with so far, but it doesn't seem to work correctly:
if [[ ! "${URL}" == *[abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890-_/&?:.=]* ]]; then
echo "That URL is NOT allowed."
else
echo "That URL is allowed."
fi
Please note that the URLs I provided in the example are just examples.
This script needs to work with all possible user input; it just can't contain characters other than the ones I specified earlier.
Using bash 3.2.57(1)-release under macOS High Sierra 10.13.6.
bash text-processing osx variable
New contributor
I want to prompt the user to input a URL, but it can only contain A-Z
, a-z
, 0-9
, &
, .
, /
, =
, _
, -
, :
, and ?
.
So, for example:
Enter URL:
$ http://youtube.com/watch?v=1234df_AQ-x
That URL is allowed.
Enter URL:
$ https://unix.stackexchange.com/$FAKEurl%🍺123
That URL is NOT allowed.
This is what I've come up with so far, but it doesn't seem to work correctly:
if [[ ! "${URL}" == *[abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890-_/&?:.=]* ]]; then
echo "That URL is NOT allowed."
else
echo "That URL is allowed."
fi
Please note that the URLs I provided in the example are just examples.
This script needs to work with all possible user input; it just can't contain characters other than the ones I specified earlier.
Using bash 3.2.57(1)-release under macOS High Sierra 10.13.6.
bash text-processing osx variable
bash text-processing osx variable
New contributor
New contributor
edited 2 hours ago
G-Man
13.1k93465
13.1k93465
New contributor
asked 6 hours ago
leetbacoonleetbacoon
112
112
New contributor
New contributor
add a comment |
add a comment |
4 Answers
4
active
oldest
votes
Another way is with a plain case
statement:
#!/bin/sh
case $URL in
(*[!A-Za-z0-9&./=_:?-]*) echo not allowed;;
(*) echo allowed;;
esac
The basic idea is to invert the logic and ask if there are any characters in the argument that are not in the allowed range.
add a comment |
Your attempt
Your attempt might not work as expected because it considers all URLs as allowed that contain at least one of the allowed characters. Formally, you compare the URL with
<anything><allowed_character><anything>
If this does not match, you reject the URL.
This might help
If you replace your if ... else ... fi
by
if [[ "${URL}" =~ [^A-Za-z0-9&./=_:?-] ]]; then
echo "That URL is NOT allowed."
else
echo "That URL is allowed."
fi
it might do what you want.
Here, the binary operator =~
is used to find a match of the regular expression [^A-Za-z0-9&./=_-:?]
within "${URL}"
. This operator does not require that the whole string "${URL}"
matches the regular expression, any matching substring will do. Such a match is found for any character that is not allowed in the URL. The "not" comes from the leading caret (^
) in the definition of the character set. Please note that there is no negating !
in the conditional expression any more.
If "${URL}"
contains a forbidden character, the regular expression matches and the compound command [[...]]
evaluates to true (zero exit status).
Just tried this withhttps://www.youtube.com/watch?v=_!
as a sample URL, but it says it's allowed...
– leetbacoon
5 hours ago
@leetbacoon: Sorry, you are absolutely right. I made a mistake in the regular expression: Defining the character set, I did not place the single-
at the end, so it was defining the character range_-:
. The collate setting in my locale covered that problem. But when the C locale is used, the[[...]]
returned exit code 2 for error, which in this case "allows" the URL. Now this is fixed.
– Jürgen
1 hour ago
add a comment |
Your current logic is wrong, it returns true only when every character in the input URL exists outside the set of permitted characters.
Try something along the lines of
if [[ "${URL}" = *[!A-Za-z0-9&./=_:?-]* ]]
then
echo "That URL is NOT allowed."
else
echo "That URL is allowed"
fi
This check, due to the negation (!) inside the character range, is intended to return true when the input URL contains one or more characters outside of the permitted set
add a comment |
Compact solution
If you prefer a compact solution, you can use this one:
[ "${URL//[A-Za-z0-9&./=_:?-]}" ] && echo No || echo Yes
Explanation
This solution uses a parameter expansion of the form ${<variable>//<pattern>}
which is a special case of the more general form
${<variable>//<pattern>/<replace>}
This is expanded by the shell to the value of <variable>
, where all matches of <pattern>
are replaced by <replace>
. In our case, <replace>
is empty, what also allows to omit the slash after <pattern>
.
As a result, "${URL//[A-Za-z0-9&./=_:?-]}"
is expanded to the URL with all allowed characters removed. If there are no residues, i.e. the URL is allowed, [ ... ]
is actually [ ]
, which yields false (exit status 0). If there are characters left, they are forbidden, and [ ... ]
has the form [ <nes> ]
, where <nes>
is a non-empty string, which yields true (exit status 1).
The overall command is a list of three commands separated by the control operators &&
(and) and ||
(or), which are left-associative. Therefore, the sub-list
[ "${URL//[A-Za-z0-9&./=_:?-]}" ] && echo No
is evaluated first. There, the second operand of &&
is evaluated if and only if the first one evaluates to true (zero exit status). This is the case if the URL contains forbidden characters. So, the echo
gives the right answer in this case, "No", and the exit status of that sub-list comes from this echo
command: 0 (true).
If, in contrast, the URL is allowed, the exit status of that sub-list comes from [ ... ]
: 1 (false).
Now for the rest of the list:
<sub-list> || echo Yes
The ||
operator executes the last command if and only if its first operand is false (exit status different from zero). So we get the "Yes" only if <sub-list>
is false, i.e. for an allowed URL, as it should be.
If structure
Of course you can use the above [ ... ]
command also in an if
structure. In most cases this will yield a better readable code:
if [ "${URL//[A-Za-z0-9&./=_:?-]}" ]; then
echo "That URL is NOT allowed."
else
echo "That URL is allowed."
fi
No need to escape the slash in the[...]
group.
– Kusalananda
4 mins ago
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
});
}
});
leetbacoon 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%2f498699%2fhow-to-allow-only-certain-characters-in-a-bash-variable%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
4 Answers
4
active
oldest
votes
4 Answers
4
active
oldest
votes
active
oldest
votes
active
oldest
votes
Another way is with a plain case
statement:
#!/bin/sh
case $URL in
(*[!A-Za-z0-9&./=_:?-]*) echo not allowed;;
(*) echo allowed;;
esac
The basic idea is to invert the logic and ask if there are any characters in the argument that are not in the allowed range.
add a comment |
Another way is with a plain case
statement:
#!/bin/sh
case $URL in
(*[!A-Za-z0-9&./=_:?-]*) echo not allowed;;
(*) echo allowed;;
esac
The basic idea is to invert the logic and ask if there are any characters in the argument that are not in the allowed range.
add a comment |
Another way is with a plain case
statement:
#!/bin/sh
case $URL in
(*[!A-Za-z0-9&./=_:?-]*) echo not allowed;;
(*) echo allowed;;
esac
The basic idea is to invert the logic and ask if there are any characters in the argument that are not in the allowed range.
Another way is with a plain case
statement:
#!/bin/sh
case $URL in
(*[!A-Za-z0-9&./=_:?-]*) echo not allowed;;
(*) echo allowed;;
esac
The basic idea is to invert the logic and ask if there are any characters in the argument that are not in the allowed range.
edited 7 mins ago
Kusalananda
128k16241398
128k16241398
answered 4 hours ago
Jeff SchallerJeff Schaller
40.9k1056130
40.9k1056130
add a comment |
add a comment |
Your attempt
Your attempt might not work as expected because it considers all URLs as allowed that contain at least one of the allowed characters. Formally, you compare the URL with
<anything><allowed_character><anything>
If this does not match, you reject the URL.
This might help
If you replace your if ... else ... fi
by
if [[ "${URL}" =~ [^A-Za-z0-9&./=_:?-] ]]; then
echo "That URL is NOT allowed."
else
echo "That URL is allowed."
fi
it might do what you want.
Here, the binary operator =~
is used to find a match of the regular expression [^A-Za-z0-9&./=_-:?]
within "${URL}"
. This operator does not require that the whole string "${URL}"
matches the regular expression, any matching substring will do. Such a match is found for any character that is not allowed in the URL. The "not" comes from the leading caret (^
) in the definition of the character set. Please note that there is no negating !
in the conditional expression any more.
If "${URL}"
contains a forbidden character, the regular expression matches and the compound command [[...]]
evaluates to true (zero exit status).
Just tried this withhttps://www.youtube.com/watch?v=_!
as a sample URL, but it says it's allowed...
– leetbacoon
5 hours ago
@leetbacoon: Sorry, you are absolutely right. I made a mistake in the regular expression: Defining the character set, I did not place the single-
at the end, so it was defining the character range_-:
. The collate setting in my locale covered that problem. But when the C locale is used, the[[...]]
returned exit code 2 for error, which in this case "allows" the URL. Now this is fixed.
– Jürgen
1 hour ago
add a comment |
Your attempt
Your attempt might not work as expected because it considers all URLs as allowed that contain at least one of the allowed characters. Formally, you compare the URL with
<anything><allowed_character><anything>
If this does not match, you reject the URL.
This might help
If you replace your if ... else ... fi
by
if [[ "${URL}" =~ [^A-Za-z0-9&./=_:?-] ]]; then
echo "That URL is NOT allowed."
else
echo "That URL is allowed."
fi
it might do what you want.
Here, the binary operator =~
is used to find a match of the regular expression [^A-Za-z0-9&./=_-:?]
within "${URL}"
. This operator does not require that the whole string "${URL}"
matches the regular expression, any matching substring will do. Such a match is found for any character that is not allowed in the URL. The "not" comes from the leading caret (^
) in the definition of the character set. Please note that there is no negating !
in the conditional expression any more.
If "${URL}"
contains a forbidden character, the regular expression matches and the compound command [[...]]
evaluates to true (zero exit status).
Just tried this withhttps://www.youtube.com/watch?v=_!
as a sample URL, but it says it's allowed...
– leetbacoon
5 hours ago
@leetbacoon: Sorry, you are absolutely right. I made a mistake in the regular expression: Defining the character set, I did not place the single-
at the end, so it was defining the character range_-:
. The collate setting in my locale covered that problem. But when the C locale is used, the[[...]]
returned exit code 2 for error, which in this case "allows" the URL. Now this is fixed.
– Jürgen
1 hour ago
add a comment |
Your attempt
Your attempt might not work as expected because it considers all URLs as allowed that contain at least one of the allowed characters. Formally, you compare the URL with
<anything><allowed_character><anything>
If this does not match, you reject the URL.
This might help
If you replace your if ... else ... fi
by
if [[ "${URL}" =~ [^A-Za-z0-9&./=_:?-] ]]; then
echo "That URL is NOT allowed."
else
echo "That URL is allowed."
fi
it might do what you want.
Here, the binary operator =~
is used to find a match of the regular expression [^A-Za-z0-9&./=_-:?]
within "${URL}"
. This operator does not require that the whole string "${URL}"
matches the regular expression, any matching substring will do. Such a match is found for any character that is not allowed in the URL. The "not" comes from the leading caret (^
) in the definition of the character set. Please note that there is no negating !
in the conditional expression any more.
If "${URL}"
contains a forbidden character, the regular expression matches and the compound command [[...]]
evaluates to true (zero exit status).
Your attempt
Your attempt might not work as expected because it considers all URLs as allowed that contain at least one of the allowed characters. Formally, you compare the URL with
<anything><allowed_character><anything>
If this does not match, you reject the URL.
This might help
If you replace your if ... else ... fi
by
if [[ "${URL}" =~ [^A-Za-z0-9&./=_:?-] ]]; then
echo "That URL is NOT allowed."
else
echo "That URL is allowed."
fi
it might do what you want.
Here, the binary operator =~
is used to find a match of the regular expression [^A-Za-z0-9&./=_-:?]
within "${URL}"
. This operator does not require that the whole string "${URL}"
matches the regular expression, any matching substring will do. Such a match is found for any character that is not allowed in the URL. The "not" comes from the leading caret (^
) in the definition of the character set. Please note that there is no negating !
in the conditional expression any more.
If "${URL}"
contains a forbidden character, the regular expression matches and the compound command [[...]]
evaluates to true (zero exit status).
edited 1 hour ago
answered 5 hours ago
JürgenJürgen
1488
1488
Just tried this withhttps://www.youtube.com/watch?v=_!
as a sample URL, but it says it's allowed...
– leetbacoon
5 hours ago
@leetbacoon: Sorry, you are absolutely right. I made a mistake in the regular expression: Defining the character set, I did not place the single-
at the end, so it was defining the character range_-:
. The collate setting in my locale covered that problem. But when the C locale is used, the[[...]]
returned exit code 2 for error, which in this case "allows" the URL. Now this is fixed.
– Jürgen
1 hour ago
add a comment |
Just tried this withhttps://www.youtube.com/watch?v=_!
as a sample URL, but it says it's allowed...
– leetbacoon
5 hours ago
@leetbacoon: Sorry, you are absolutely right. I made a mistake in the regular expression: Defining the character set, I did not place the single-
at the end, so it was defining the character range_-:
. The collate setting in my locale covered that problem. But when the C locale is used, the[[...]]
returned exit code 2 for error, which in this case "allows" the URL. Now this is fixed.
– Jürgen
1 hour ago
Just tried this with
https://www.youtube.com/watch?v=_!
as a sample URL, but it says it's allowed...– leetbacoon
5 hours ago
Just tried this with
https://www.youtube.com/watch?v=_!
as a sample URL, but it says it's allowed...– leetbacoon
5 hours ago
@leetbacoon: Sorry, you are absolutely right. I made a mistake in the regular expression: Defining the character set, I did not place the single
-
at the end, so it was defining the character range _-:
. The collate setting in my locale covered that problem. But when the C locale is used, the [[...]]
returned exit code 2 for error, which in this case "allows" the URL. Now this is fixed.– Jürgen
1 hour ago
@leetbacoon: Sorry, you are absolutely right. I made a mistake in the regular expression: Defining the character set, I did not place the single
-
at the end, so it was defining the character range _-:
. The collate setting in my locale covered that problem. But when the C locale is used, the [[...]]
returned exit code 2 for error, which in this case "allows" the URL. Now this is fixed.– Jürgen
1 hour ago
add a comment |
Your current logic is wrong, it returns true only when every character in the input URL exists outside the set of permitted characters.
Try something along the lines of
if [[ "${URL}" = *[!A-Za-z0-9&./=_:?-]* ]]
then
echo "That URL is NOT allowed."
else
echo "That URL is allowed"
fi
This check, due to the negation (!) inside the character range, is intended to return true when the input URL contains one or more characters outside of the permitted set
add a comment |
Your current logic is wrong, it returns true only when every character in the input URL exists outside the set of permitted characters.
Try something along the lines of
if [[ "${URL}" = *[!A-Za-z0-9&./=_:?-]* ]]
then
echo "That URL is NOT allowed."
else
echo "That URL is allowed"
fi
This check, due to the negation (!) inside the character range, is intended to return true when the input URL contains one or more characters outside of the permitted set
add a comment |
Your current logic is wrong, it returns true only when every character in the input URL exists outside the set of permitted characters.
Try something along the lines of
if [[ "${URL}" = *[!A-Za-z0-9&./=_:?-]* ]]
then
echo "That URL is NOT allowed."
else
echo "That URL is allowed"
fi
This check, due to the negation (!) inside the character range, is intended to return true when the input URL contains one or more characters outside of the permitted set
Your current logic is wrong, it returns true only when every character in the input URL exists outside the set of permitted characters.
Try something along the lines of
if [[ "${URL}" = *[!A-Za-z0-9&./=_:?-]* ]]
then
echo "That URL is NOT allowed."
else
echo "That URL is allowed"
fi
This check, due to the negation (!) inside the character range, is intended to return true when the input URL contains one or more characters outside of the permitted set
answered 4 hours ago
iruvariruvar
11.8k62960
11.8k62960
add a comment |
add a comment |
Compact solution
If you prefer a compact solution, you can use this one:
[ "${URL//[A-Za-z0-9&./=_:?-]}" ] && echo No || echo Yes
Explanation
This solution uses a parameter expansion of the form ${<variable>//<pattern>}
which is a special case of the more general form
${<variable>//<pattern>/<replace>}
This is expanded by the shell to the value of <variable>
, where all matches of <pattern>
are replaced by <replace>
. In our case, <replace>
is empty, what also allows to omit the slash after <pattern>
.
As a result, "${URL//[A-Za-z0-9&./=_:?-]}"
is expanded to the URL with all allowed characters removed. If there are no residues, i.e. the URL is allowed, [ ... ]
is actually [ ]
, which yields false (exit status 0). If there are characters left, they are forbidden, and [ ... ]
has the form [ <nes> ]
, where <nes>
is a non-empty string, which yields true (exit status 1).
The overall command is a list of three commands separated by the control operators &&
(and) and ||
(or), which are left-associative. Therefore, the sub-list
[ "${URL//[A-Za-z0-9&./=_:?-]}" ] && echo No
is evaluated first. There, the second operand of &&
is evaluated if and only if the first one evaluates to true (zero exit status). This is the case if the URL contains forbidden characters. So, the echo
gives the right answer in this case, "No", and the exit status of that sub-list comes from this echo
command: 0 (true).
If, in contrast, the URL is allowed, the exit status of that sub-list comes from [ ... ]
: 1 (false).
Now for the rest of the list:
<sub-list> || echo Yes
The ||
operator executes the last command if and only if its first operand is false (exit status different from zero). So we get the "Yes" only if <sub-list>
is false, i.e. for an allowed URL, as it should be.
If structure
Of course you can use the above [ ... ]
command also in an if
structure. In most cases this will yield a better readable code:
if [ "${URL//[A-Za-z0-9&./=_:?-]}" ]; then
echo "That URL is NOT allowed."
else
echo "That URL is allowed."
fi
No need to escape the slash in the[...]
group.
– Kusalananda
4 mins ago
add a comment |
Compact solution
If you prefer a compact solution, you can use this one:
[ "${URL//[A-Za-z0-9&./=_:?-]}" ] && echo No || echo Yes
Explanation
This solution uses a parameter expansion of the form ${<variable>//<pattern>}
which is a special case of the more general form
${<variable>//<pattern>/<replace>}
This is expanded by the shell to the value of <variable>
, where all matches of <pattern>
are replaced by <replace>
. In our case, <replace>
is empty, what also allows to omit the slash after <pattern>
.
As a result, "${URL//[A-Za-z0-9&./=_:?-]}"
is expanded to the URL with all allowed characters removed. If there are no residues, i.e. the URL is allowed, [ ... ]
is actually [ ]
, which yields false (exit status 0). If there are characters left, they are forbidden, and [ ... ]
has the form [ <nes> ]
, where <nes>
is a non-empty string, which yields true (exit status 1).
The overall command is a list of three commands separated by the control operators &&
(and) and ||
(or), which are left-associative. Therefore, the sub-list
[ "${URL//[A-Za-z0-9&./=_:?-]}" ] && echo No
is evaluated first. There, the second operand of &&
is evaluated if and only if the first one evaluates to true (zero exit status). This is the case if the URL contains forbidden characters. So, the echo
gives the right answer in this case, "No", and the exit status of that sub-list comes from this echo
command: 0 (true).
If, in contrast, the URL is allowed, the exit status of that sub-list comes from [ ... ]
: 1 (false).
Now for the rest of the list:
<sub-list> || echo Yes
The ||
operator executes the last command if and only if its first operand is false (exit status different from zero). So we get the "Yes" only if <sub-list>
is false, i.e. for an allowed URL, as it should be.
If structure
Of course you can use the above [ ... ]
command also in an if
structure. In most cases this will yield a better readable code:
if [ "${URL//[A-Za-z0-9&./=_:?-]}" ]; then
echo "That URL is NOT allowed."
else
echo "That URL is allowed."
fi
No need to escape the slash in the[...]
group.
– Kusalananda
4 mins ago
add a comment |
Compact solution
If you prefer a compact solution, you can use this one:
[ "${URL//[A-Za-z0-9&./=_:?-]}" ] && echo No || echo Yes
Explanation
This solution uses a parameter expansion of the form ${<variable>//<pattern>}
which is a special case of the more general form
${<variable>//<pattern>/<replace>}
This is expanded by the shell to the value of <variable>
, where all matches of <pattern>
are replaced by <replace>
. In our case, <replace>
is empty, what also allows to omit the slash after <pattern>
.
As a result, "${URL//[A-Za-z0-9&./=_:?-]}"
is expanded to the URL with all allowed characters removed. If there are no residues, i.e. the URL is allowed, [ ... ]
is actually [ ]
, which yields false (exit status 0). If there are characters left, they are forbidden, and [ ... ]
has the form [ <nes> ]
, where <nes>
is a non-empty string, which yields true (exit status 1).
The overall command is a list of three commands separated by the control operators &&
(and) and ||
(or), which are left-associative. Therefore, the sub-list
[ "${URL//[A-Za-z0-9&./=_:?-]}" ] && echo No
is evaluated first. There, the second operand of &&
is evaluated if and only if the first one evaluates to true (zero exit status). This is the case if the URL contains forbidden characters. So, the echo
gives the right answer in this case, "No", and the exit status of that sub-list comes from this echo
command: 0 (true).
If, in contrast, the URL is allowed, the exit status of that sub-list comes from [ ... ]
: 1 (false).
Now for the rest of the list:
<sub-list> || echo Yes
The ||
operator executes the last command if and only if its first operand is false (exit status different from zero). So we get the "Yes" only if <sub-list>
is false, i.e. for an allowed URL, as it should be.
If structure
Of course you can use the above [ ... ]
command also in an if
structure. In most cases this will yield a better readable code:
if [ "${URL//[A-Za-z0-9&./=_:?-]}" ]; then
echo "That URL is NOT allowed."
else
echo "That URL is allowed."
fi
Compact solution
If you prefer a compact solution, you can use this one:
[ "${URL//[A-Za-z0-9&./=_:?-]}" ] && echo No || echo Yes
Explanation
This solution uses a parameter expansion of the form ${<variable>//<pattern>}
which is a special case of the more general form
${<variable>//<pattern>/<replace>}
This is expanded by the shell to the value of <variable>
, where all matches of <pattern>
are replaced by <replace>
. In our case, <replace>
is empty, what also allows to omit the slash after <pattern>
.
As a result, "${URL//[A-Za-z0-9&./=_:?-]}"
is expanded to the URL with all allowed characters removed. If there are no residues, i.e. the URL is allowed, [ ... ]
is actually [ ]
, which yields false (exit status 0). If there are characters left, they are forbidden, and [ ... ]
has the form [ <nes> ]
, where <nes>
is a non-empty string, which yields true (exit status 1).
The overall command is a list of three commands separated by the control operators &&
(and) and ||
(or), which are left-associative. Therefore, the sub-list
[ "${URL//[A-Za-z0-9&./=_:?-]}" ] && echo No
is evaluated first. There, the second operand of &&
is evaluated if and only if the first one evaluates to true (zero exit status). This is the case if the URL contains forbidden characters. So, the echo
gives the right answer in this case, "No", and the exit status of that sub-list comes from this echo
command: 0 (true).
If, in contrast, the URL is allowed, the exit status of that sub-list comes from [ ... ]
: 1 (false).
Now for the rest of the list:
<sub-list> || echo Yes
The ||
operator executes the last command if and only if its first operand is false (exit status different from zero). So we get the "Yes" only if <sub-list>
is false, i.e. for an allowed URL, as it should be.
If structure
Of course you can use the above [ ... ]
command also in an if
structure. In most cases this will yield a better readable code:
if [ "${URL//[A-Za-z0-9&./=_:?-]}" ]; then
echo "That URL is NOT allowed."
else
echo "That URL is allowed."
fi
edited 19 mins ago
answered 32 mins ago
JürgenJürgen
1488
1488
No need to escape the slash in the[...]
group.
– Kusalananda
4 mins ago
add a comment |
No need to escape the slash in the[...]
group.
– Kusalananda
4 mins ago
No need to escape the slash in the
[...]
group.– Kusalananda
4 mins ago
No need to escape the slash in the
[...]
group.– Kusalananda
4 mins ago
add a comment |
leetbacoon is a new contributor. Be nice, and check out our Code of Conduct.
leetbacoon is a new contributor. Be nice, and check out our Code of Conduct.
leetbacoon is a new contributor. Be nice, and check out our Code of Conduct.
leetbacoon 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%2f498699%2fhow-to-allow-only-certain-characters-in-a-bash-variable%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