How to allow only certain characters in a bash variable
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ margin-bottom:0;
}
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
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
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
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
edited Feb 5 at 4:23
G-Man
13.7k93870
13.7k93870
asked Feb 5 at 0:36
leetbacoonleetbacoon
285
285
add a comment |
add a comment |
4 Answers
4
active
oldest
votes
You were close.
You want to check whether the URL contains at least one of the disallowed characters (and then report it as invalid), not at least one of the allowed character.
You can negate a character set in a bracket expression with ! (^ also works with bash and a few other shells).
In any case, you were right to explicitly list characters individually, using ranges like a-z, A-Z, 0-9 would only work (at matching only the 26+26+10 characters you listed) in the C locale. In other locales they could match thousands of other characters or even collating elements made of more than one character (the ones that sort between A and Z like É for instance for A-Z).
case $URL in
("" | *[!abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890_/&?:.=-]*)
echo >&2 "That URL is NOT allowed.";;
(*)
echo "That URL is allowed.";;
esac
Works nicely. Now, regarding the$URLincase $URL in, shouldn't it be wrapped in quotes, i.e.case "${URL}" in?
– leetbacoon
Feb 10 at 22:45
@leetbacoon, while those quotes wouldn't harm, they are nor necessary, as it's not a list context (so split+glob won't apply) and it's not a context where a pattern is expected (it would be a different matter incase x in ("$URL")...
– Stéphane Chazelas
Feb 17 at 15:02
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
Feb 5 at 1:37
@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
Feb 5 at 5:18
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
Tested and also working A-OK! :)
– leetbacoon
Feb 10 at 22:54
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♦
Feb 5 at 6:48
@Kusalananda: Actually, the slash has to be escaped, since it is otherwise mistaken as a part of the parameter expression, which yields${..//../..}instead of${..//..}. The former does simply not work.
– Jürgen
Feb 5 at 14:07
Also tested and working great. I like the compact idea!
– leetbacoon
Feb 10 at 22:54
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
});
}
});
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
You were close.
You want to check whether the URL contains at least one of the disallowed characters (and then report it as invalid), not at least one of the allowed character.
You can negate a character set in a bracket expression with ! (^ also works with bash and a few other shells).
In any case, you were right to explicitly list characters individually, using ranges like a-z, A-Z, 0-9 would only work (at matching only the 26+26+10 characters you listed) in the C locale. In other locales they could match thousands of other characters or even collating elements made of more than one character (the ones that sort between A and Z like É for instance for A-Z).
case $URL in
("" | *[!abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890_/&?:.=-]*)
echo >&2 "That URL is NOT allowed.";;
(*)
echo "That URL is allowed.";;
esac
Works nicely. Now, regarding the$URLincase $URL in, shouldn't it be wrapped in quotes, i.e.case "${URL}" in?
– leetbacoon
Feb 10 at 22:45
@leetbacoon, while those quotes wouldn't harm, they are nor necessary, as it's not a list context (so split+glob won't apply) and it's not a context where a pattern is expected (it would be a different matter incase x in ("$URL")...
– Stéphane Chazelas
Feb 17 at 15:02
add a comment |
You were close.
You want to check whether the URL contains at least one of the disallowed characters (and then report it as invalid), not at least one of the allowed character.
You can negate a character set in a bracket expression with ! (^ also works with bash and a few other shells).
In any case, you were right to explicitly list characters individually, using ranges like a-z, A-Z, 0-9 would only work (at matching only the 26+26+10 characters you listed) in the C locale. In other locales they could match thousands of other characters or even collating elements made of more than one character (the ones that sort between A and Z like É for instance for A-Z).
case $URL in
("" | *[!abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890_/&?:.=-]*)
echo >&2 "That URL is NOT allowed.";;
(*)
echo "That URL is allowed.";;
esac
Works nicely. Now, regarding the$URLincase $URL in, shouldn't it be wrapped in quotes, i.e.case "${URL}" in?
– leetbacoon
Feb 10 at 22:45
@leetbacoon, while those quotes wouldn't harm, they are nor necessary, as it's not a list context (so split+glob won't apply) and it's not a context where a pattern is expected (it would be a different matter incase x in ("$URL")...
– Stéphane Chazelas
Feb 17 at 15:02
add a comment |
You were close.
You want to check whether the URL contains at least one of the disallowed characters (and then report it as invalid), not at least one of the allowed character.
You can negate a character set in a bracket expression with ! (^ also works with bash and a few other shells).
In any case, you were right to explicitly list characters individually, using ranges like a-z, A-Z, 0-9 would only work (at matching only the 26+26+10 characters you listed) in the C locale. In other locales they could match thousands of other characters or even collating elements made of more than one character (the ones that sort between A and Z like É for instance for A-Z).
case $URL in
("" | *[!abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890_/&?:.=-]*)
echo >&2 "That URL is NOT allowed.";;
(*)
echo "That URL is allowed.";;
esac
You were close.
You want to check whether the URL contains at least one of the disallowed characters (and then report it as invalid), not at least one of the allowed character.
You can negate a character set in a bracket expression with ! (^ also works with bash and a few other shells).
In any case, you were right to explicitly list characters individually, using ranges like a-z, A-Z, 0-9 would only work (at matching only the 26+26+10 characters you listed) in the C locale. In other locales they could match thousands of other characters or even collating elements made of more than one character (the ones that sort between A and Z like É for instance for A-Z).
case $URL in
("" | *[!abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890_/&?:.=-]*)
echo >&2 "That URL is NOT allowed.";;
(*)
echo "That URL is allowed.";;
esac
edited Feb 5 at 8:28
answered Feb 5 at 7:47
Stéphane ChazelasStéphane Chazelas
315k57597955
315k57597955
Works nicely. Now, regarding the$URLincase $URL in, shouldn't it be wrapped in quotes, i.e.case "${URL}" in?
– leetbacoon
Feb 10 at 22:45
@leetbacoon, while those quotes wouldn't harm, they are nor necessary, as it's not a list context (so split+glob won't apply) and it's not a context where a pattern is expected (it would be a different matter incase x in ("$URL")...
– Stéphane Chazelas
Feb 17 at 15:02
add a comment |
Works nicely. Now, regarding the$URLincase $URL in, shouldn't it be wrapped in quotes, i.e.case "${URL}" in?
– leetbacoon
Feb 10 at 22:45
@leetbacoon, while those quotes wouldn't harm, they are nor necessary, as it's not a list context (so split+glob won't apply) and it's not a context where a pattern is expected (it would be a different matter incase x in ("$URL")...
– Stéphane Chazelas
Feb 17 at 15:02
Works nicely. Now, regarding the
$URL in case $URL in, shouldn't it be wrapped in quotes, i.e. case "${URL}" in?– leetbacoon
Feb 10 at 22:45
Works nicely. Now, regarding the
$URL in case $URL in, shouldn't it be wrapped in quotes, i.e. case "${URL}" in?– leetbacoon
Feb 10 at 22:45
@leetbacoon, while those quotes wouldn't harm, they are nor necessary, as it's not a list context (so split+glob won't apply) and it's not a context where a pattern is expected (it would be a different matter in
case x in ("$URL")...– Stéphane Chazelas
Feb 17 at 15:02
@leetbacoon, while those quotes wouldn't harm, they are nor necessary, as it's not a list context (so split+glob won't apply) and it's not a context where a pattern is expected (it would be a different matter in
case x in ("$URL")...– Stéphane Chazelas
Feb 17 at 15:02
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
Feb 5 at 1:37
@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
Feb 5 at 5:18
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
Feb 5 at 1:37
@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
Feb 5 at 5:18
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 Feb 5 at 5:11
answered Feb 5 at 0:59
JürgenJürgen
192110
192110
Just tried this withhttps://www.youtube.com/watch?v=_!as a sample URL, but it says it's allowed...
– leetbacoon
Feb 5 at 1:37
@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
Feb 5 at 5:18
add a comment |
Just tried this withhttps://www.youtube.com/watch?v=_!as a sample URL, but it says it's allowed...
– leetbacoon
Feb 5 at 1:37
@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
Feb 5 at 5:18
Just tried this with
https://www.youtube.com/watch?v=_! as a sample URL, but it says it's allowed...– leetbacoon
Feb 5 at 1:37
Just tried this with
https://www.youtube.com/watch?v=_! as a sample URL, but it says it's allowed...– leetbacoon
Feb 5 at 1:37
@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
Feb 5 at 5:18
@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
Feb 5 at 5:18
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
Tested and also working A-OK! :)
– leetbacoon
Feb 10 at 22:54
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
Tested and also working A-OK! :)
– leetbacoon
Feb 10 at 22:54
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 Feb 5 at 1:58
iruvariruvar
12.5k63063
12.5k63063
Tested and also working A-OK! :)
– leetbacoon
Feb 10 at 22:54
add a comment |
Tested and also working A-OK! :)
– leetbacoon
Feb 10 at 22:54
Tested and also working A-OK! :)
– leetbacoon
Feb 10 at 22:54
Tested and also working A-OK! :)
– leetbacoon
Feb 10 at 22:54
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♦
Feb 5 at 6:48
@Kusalananda: Actually, the slash has to be escaped, since it is otherwise mistaken as a part of the parameter expression, which yields${..//../..}instead of${..//..}. The former does simply not work.
– Jürgen
Feb 5 at 14:07
Also tested and working great. I like the compact idea!
– leetbacoon
Feb 10 at 22:54
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♦
Feb 5 at 6:48
@Kusalananda: Actually, the slash has to be escaped, since it is otherwise mistaken as a part of the parameter expression, which yields${..//../..}instead of${..//..}. The former does simply not work.
– Jürgen
Feb 5 at 14:07
Also tested and working great. I like the compact idea!
– leetbacoon
Feb 10 at 22:54
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 Feb 5 at 6:34
answered Feb 5 at 6:21
JürgenJürgen
192110
192110
No need to escape the slash in the[...]group.
– Kusalananda♦
Feb 5 at 6:48
@Kusalananda: Actually, the slash has to be escaped, since it is otherwise mistaken as a part of the parameter expression, which yields${..//../..}instead of${..//..}. The former does simply not work.
– Jürgen
Feb 5 at 14:07
Also tested and working great. I like the compact idea!
– leetbacoon
Feb 10 at 22:54
add a comment |
No need to escape the slash in the[...]group.
– Kusalananda♦
Feb 5 at 6:48
@Kusalananda: Actually, the slash has to be escaped, since it is otherwise mistaken as a part of the parameter expression, which yields${..//../..}instead of${..//..}. The former does simply not work.
– Jürgen
Feb 5 at 14:07
Also tested and working great. I like the compact idea!
– leetbacoon
Feb 10 at 22:54
No need to escape the slash in the
[...] group.– Kusalananda♦
Feb 5 at 6:48
No need to escape the slash in the
[...] group.– Kusalananda♦
Feb 5 at 6:48
@Kusalananda: Actually, the slash has to be escaped, since it is otherwise mistaken as a part of the parameter expression, which yields
${..//../..} instead of ${..//..}. The former does simply not work.– Jürgen
Feb 5 at 14:07
@Kusalananda: Actually, the slash has to be escaped, since it is otherwise mistaken as a part of the parameter expression, which yields
${..//../..} instead of ${..//..}. The former does simply not work.– Jürgen
Feb 5 at 14:07
Also tested and working great. I like the compact idea!
– leetbacoon
Feb 10 at 22:54
Also tested and working great. I like the compact idea!
– leetbacoon
Feb 10 at 22:54
add a comment |
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