How to allow only certain characters in a bash variable












2















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.










share|improve this question









New contributor




leetbacoon is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.

























    2















    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.










    share|improve this question









    New contributor




    leetbacoon is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
    Check out our Code of Conduct.























      2












      2








      2


      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.










      share|improve this question









      New contributor




      leetbacoon is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.












      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






      share|improve this question









      New contributor




      leetbacoon is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.











      share|improve this question









      New contributor




      leetbacoon is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.









      share|improve this question




      share|improve this question








      edited 2 hours ago









      G-Man

      13.1k93465




      13.1k93465






      New contributor




      leetbacoon is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.









      asked 6 hours ago









      leetbacoonleetbacoon

      112




      112




      New contributor




      leetbacoon is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.





      New contributor





      leetbacoon is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.






      leetbacoon is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.






















          4 Answers
          4






          active

          oldest

          votes


















          2














          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.






          share|improve this answer

































            1














            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).






            share|improve this answer


























            • 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



















            0














            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






            share|improve this answer































              0














              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





              share|improve this answer


























              • No need to escape the slash in the [...] group.

                – Kusalananda
                6 mins ago











              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.










              draft saved

              draft discarded


















              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









              2














              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.






              share|improve this answer






























                2














                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.






                share|improve this answer




























                  2












                  2








                  2







                  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.






                  share|improve this answer















                  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.







                  share|improve this answer














                  share|improve this answer



                  share|improve this answer








                  edited 9 mins ago









                  Kusalananda

                  128k16241398




                  128k16241398










                  answered 4 hours ago









                  Jeff SchallerJeff Schaller

                  40.9k1056130




                  40.9k1056130

























                      1














                      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).






                      share|improve this answer


























                      • 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
















                      1














                      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).






                      share|improve this answer


























                      • 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














                      1












                      1








                      1







                      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).






                      share|improve this answer















                      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).







                      share|improve this answer














                      share|improve this answer



                      share|improve this answer








                      edited 1 hour ago

























                      answered 5 hours ago









                      JürgenJürgen

                      1488




                      1488













                      • 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



















                      • 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

















                      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











                      0














                      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






                      share|improve this answer




























                        0














                        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






                        share|improve this answer


























                          0












                          0








                          0







                          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






                          share|improve this answer













                          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







                          share|improve this answer












                          share|improve this answer



                          share|improve this answer










                          answered 4 hours ago









                          iruvariruvar

                          11.8k62960




                          11.8k62960























                              0














                              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





                              share|improve this answer


























                              • No need to escape the slash in the [...] group.

                                – Kusalananda
                                6 mins ago
















                              0














                              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





                              share|improve this answer


























                              • No need to escape the slash in the [...] group.

                                – Kusalananda
                                6 mins ago














                              0












                              0








                              0







                              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





                              share|improve this answer















                              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






                              share|improve this answer














                              share|improve this answer



                              share|improve this answer








                              edited 21 mins ago

























                              answered 34 mins ago









                              JürgenJürgen

                              1488




                              1488













                              • No need to escape the slash in the [...] group.

                                – Kusalananda
                                6 mins ago



















                              • No need to escape the slash in the [...] group.

                                – Kusalananda
                                6 mins ago

















                              No need to escape the slash in the [...] group.

                              – Kusalananda
                              6 mins ago





                              No need to escape the slash in the [...] group.

                              – Kusalananda
                              6 mins ago










                              leetbacoon is a new contributor. Be nice, and check out our Code of Conduct.










                              draft saved

                              draft discarded


















                              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.




                              draft saved


                              draft discarded














                              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





















































                              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







                              Popular posts from this blog

                              SQL Server 17 - Attemping to backup to remote NAS but Access is denied

                              Always On Availability groups resolving state after failover - Remote harden of transaction...

                              Restoring from pg_dump with foreign key constraints