bash how to improve this script

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;







up vote
4
down vote

favorite












I'm new to shell scripting and I'd like to know if there is maybe a better solution then the one I figured out:



I want to check if a user is in a list and if yes than the script should terminate with the exit_program function:



$USER is defined as somebody who logs into the system



My solution (it works) is:



$IGNORE_USER="USER1 USER2 USER3"

if [ ! -z "$IGNORE_USER" ]; then
for usr in $IGNORE_USER
do
if $USER = $usr; then
exit_program "bye bye"
fi
done
fi






share|improve this question



















  • You don't need to loop over your array of users. See here
    – xenoid
    10 hours ago










  • If you have a working script and want it reviewed, consider codereview.stackexchange.com
    – kojiro
    7 hours ago
















up vote
4
down vote

favorite












I'm new to shell scripting and I'd like to know if there is maybe a better solution then the one I figured out:



I want to check if a user is in a list and if yes than the script should terminate with the exit_program function:



$USER is defined as somebody who logs into the system



My solution (it works) is:



$IGNORE_USER="USER1 USER2 USER3"

if [ ! -z "$IGNORE_USER" ]; then
for usr in $IGNORE_USER
do
if $USER = $usr; then
exit_program "bye bye"
fi
done
fi






share|improve this question



















  • You don't need to loop over your array of users. See here
    – xenoid
    10 hours ago










  • If you have a working script and want it reviewed, consider codereview.stackexchange.com
    – kojiro
    7 hours ago












up vote
4
down vote

favorite









up vote
4
down vote

favorite











I'm new to shell scripting and I'd like to know if there is maybe a better solution then the one I figured out:



I want to check if a user is in a list and if yes than the script should terminate with the exit_program function:



$USER is defined as somebody who logs into the system



My solution (it works) is:



$IGNORE_USER="USER1 USER2 USER3"

if [ ! -z "$IGNORE_USER" ]; then
for usr in $IGNORE_USER
do
if $USER = $usr; then
exit_program "bye bye"
fi
done
fi






share|improve this question











I'm new to shell scripting and I'd like to know if there is maybe a better solution then the one I figured out:



I want to check if a user is in a list and if yes than the script should terminate with the exit_program function:



$USER is defined as somebody who logs into the system



My solution (it works) is:



$IGNORE_USER="USER1 USER2 USER3"

if [ ! -z "$IGNORE_USER" ]; then
for usr in $IGNORE_USER
do
if $USER = $usr; then
exit_program "bye bye"
fi
done
fi








share|improve this question










share|improve this question




share|improve this question









asked 13 hours ago









bernhard

212




212











  • You don't need to loop over your array of users. See here
    – xenoid
    10 hours ago










  • If you have a working script and want it reviewed, consider codereview.stackexchange.com
    – kojiro
    7 hours ago
















  • You don't need to loop over your array of users. See here
    – xenoid
    10 hours ago










  • If you have a working script and want it reviewed, consider codereview.stackexchange.com
    – kojiro
    7 hours ago















You don't need to loop over your array of users. See here
– xenoid
10 hours ago




You don't need to loop over your array of users. See here
– xenoid
10 hours ago












If you have a working script and want it reviewed, consider codereview.stackexchange.com
– kojiro
7 hours ago




If you have a working script and want it reviewed, consider codereview.stackexchange.com
– kojiro
7 hours ago










2 Answers
2






active

oldest

votes

















up vote
7
down vote













That script does not work.



You have a syntax error on the first line in that an assignment to IGNORE_USER should not dereference the variable with $.
There is another syntax error in your if statement. Use [ "string1" = "string2" ] to compare strings.



Your code relies on using $IGNORE_USER unquoted. This splits the string on whitespaces, which is what you want to do. In the most general case, this is not what you want to do, as the items in the list may well contain whitespace characters that should be preserved. The shell would also perform filename generation (globbing) on the values in the string if it's used unquoted.



It would be better to use an array for this as you're dealing with separate items (usernames). In general, whenever you want to treat separate items as separate items, don't put them inside a single string. Doing so would potentially make it hard to distinguish one item from another.



Suggestion:



ignore=( 'user1' 'user2' 'user3' )

for u in "$ignore[@]"; do
if [ "$USER" = "$u" ]; then
exit_program 'bye bye'
fi
done


This assumes that exit_program takes care of exiting the program. If not, add exit afterwards. There is no need to test whether the ignore array is empty as the loop would not run a single iteration if it was.



In the code above, "$ignore[@]" (note the double quotes) would expand to the list of usernames, each username individually quoted and protected from further word splitting and filename generation.



Related:



  • The ShellCheck website


For a version that is not specific to bash, but that would run in any POSIX-like shell:



set -- 'user1' 'user2' 'user3'

for u do
if [ "$USER" = "$u" ]; then
exit_program 'bye bye'
fi
done


This uses the list of positional parameters as the list of usernames to ignore instead of an array.






share|improve this answer






























    up vote
    3
    down vote













    grep solution



    Use the "-w" feature of grep, to match a word.
    Daresay it won't work on older grep implementations, such as Solaris, AIX etc.



    echo $IGNORE_USER | grep -qw $USER && exit_program 'bye bye'


    Try it online!



    bash internal solution



    Go entirely bash, and don't rely on grep.



    bash doesn't allow a construct of =~ regex unless you run shopt -s compat31 first. So by using the =~ $(echo regex) we can overcome this. We use double quotes in this example, so that $USER gets expanded, and in so doing we need to escape out the b to be \b.



    [[ $IGNORE_USER =~ $(echo "\b$USER\b") ]] && exit_program 'bye bye'


    Try it online!






    share|improve this answer























      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',
      convertImagesToLinks: false,
      noModals: false,
      showLowRepImageUploadWarning: true,
      reputationToPostImages: null,
      bindNavPrevention: true,
      postfix: "",
      onDemand: true,
      discardSelector: ".discard-answer"
      ,immediatelyShowMarkdownHelp:true
      );



      );








       

      draft saved


      draft discarded


















      StackExchange.ready(
      function ()
      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f460658%2fbash-how-to-improve-this-script%23new-answer', 'question_page');

      );

      Post as a guest






























      2 Answers
      2






      active

      oldest

      votes








      2 Answers
      2






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes








      up vote
      7
      down vote













      That script does not work.



      You have a syntax error on the first line in that an assignment to IGNORE_USER should not dereference the variable with $.
      There is another syntax error in your if statement. Use [ "string1" = "string2" ] to compare strings.



      Your code relies on using $IGNORE_USER unquoted. This splits the string on whitespaces, which is what you want to do. In the most general case, this is not what you want to do, as the items in the list may well contain whitespace characters that should be preserved. The shell would also perform filename generation (globbing) on the values in the string if it's used unquoted.



      It would be better to use an array for this as you're dealing with separate items (usernames). In general, whenever you want to treat separate items as separate items, don't put them inside a single string. Doing so would potentially make it hard to distinguish one item from another.



      Suggestion:



      ignore=( 'user1' 'user2' 'user3' )

      for u in "$ignore[@]"; do
      if [ "$USER" = "$u" ]; then
      exit_program 'bye bye'
      fi
      done


      This assumes that exit_program takes care of exiting the program. If not, add exit afterwards. There is no need to test whether the ignore array is empty as the loop would not run a single iteration if it was.



      In the code above, "$ignore[@]" (note the double quotes) would expand to the list of usernames, each username individually quoted and protected from further word splitting and filename generation.



      Related:



      • The ShellCheck website


      For a version that is not specific to bash, but that would run in any POSIX-like shell:



      set -- 'user1' 'user2' 'user3'

      for u do
      if [ "$USER" = "$u" ]; then
      exit_program 'bye bye'
      fi
      done


      This uses the list of positional parameters as the list of usernames to ignore instead of an array.






      share|improve this answer



























        up vote
        7
        down vote













        That script does not work.



        You have a syntax error on the first line in that an assignment to IGNORE_USER should not dereference the variable with $.
        There is another syntax error in your if statement. Use [ "string1" = "string2" ] to compare strings.



        Your code relies on using $IGNORE_USER unquoted. This splits the string on whitespaces, which is what you want to do. In the most general case, this is not what you want to do, as the items in the list may well contain whitespace characters that should be preserved. The shell would also perform filename generation (globbing) on the values in the string if it's used unquoted.



        It would be better to use an array for this as you're dealing with separate items (usernames). In general, whenever you want to treat separate items as separate items, don't put them inside a single string. Doing so would potentially make it hard to distinguish one item from another.



        Suggestion:



        ignore=( 'user1' 'user2' 'user3' )

        for u in "$ignore[@]"; do
        if [ "$USER" = "$u" ]; then
        exit_program 'bye bye'
        fi
        done


        This assumes that exit_program takes care of exiting the program. If not, add exit afterwards. There is no need to test whether the ignore array is empty as the loop would not run a single iteration if it was.



        In the code above, "$ignore[@]" (note the double quotes) would expand to the list of usernames, each username individually quoted and protected from further word splitting and filename generation.



        Related:



        • The ShellCheck website


        For a version that is not specific to bash, but that would run in any POSIX-like shell:



        set -- 'user1' 'user2' 'user3'

        for u do
        if [ "$USER" = "$u" ]; then
        exit_program 'bye bye'
        fi
        done


        This uses the list of positional parameters as the list of usernames to ignore instead of an array.






        share|improve this answer

























          up vote
          7
          down vote










          up vote
          7
          down vote









          That script does not work.



          You have a syntax error on the first line in that an assignment to IGNORE_USER should not dereference the variable with $.
          There is another syntax error in your if statement. Use [ "string1" = "string2" ] to compare strings.



          Your code relies on using $IGNORE_USER unquoted. This splits the string on whitespaces, which is what you want to do. In the most general case, this is not what you want to do, as the items in the list may well contain whitespace characters that should be preserved. The shell would also perform filename generation (globbing) on the values in the string if it's used unquoted.



          It would be better to use an array for this as you're dealing with separate items (usernames). In general, whenever you want to treat separate items as separate items, don't put them inside a single string. Doing so would potentially make it hard to distinguish one item from another.



          Suggestion:



          ignore=( 'user1' 'user2' 'user3' )

          for u in "$ignore[@]"; do
          if [ "$USER" = "$u" ]; then
          exit_program 'bye bye'
          fi
          done


          This assumes that exit_program takes care of exiting the program. If not, add exit afterwards. There is no need to test whether the ignore array is empty as the loop would not run a single iteration if it was.



          In the code above, "$ignore[@]" (note the double quotes) would expand to the list of usernames, each username individually quoted and protected from further word splitting and filename generation.



          Related:



          • The ShellCheck website


          For a version that is not specific to bash, but that would run in any POSIX-like shell:



          set -- 'user1' 'user2' 'user3'

          for u do
          if [ "$USER" = "$u" ]; then
          exit_program 'bye bye'
          fi
          done


          This uses the list of positional parameters as the list of usernames to ignore instead of an array.






          share|improve this answer















          That script does not work.



          You have a syntax error on the first line in that an assignment to IGNORE_USER should not dereference the variable with $.
          There is another syntax error in your if statement. Use [ "string1" = "string2" ] to compare strings.



          Your code relies on using $IGNORE_USER unquoted. This splits the string on whitespaces, which is what you want to do. In the most general case, this is not what you want to do, as the items in the list may well contain whitespace characters that should be preserved. The shell would also perform filename generation (globbing) on the values in the string if it's used unquoted.



          It would be better to use an array for this as you're dealing with separate items (usernames). In general, whenever you want to treat separate items as separate items, don't put them inside a single string. Doing so would potentially make it hard to distinguish one item from another.



          Suggestion:



          ignore=( 'user1' 'user2' 'user3' )

          for u in "$ignore[@]"; do
          if [ "$USER" = "$u" ]; then
          exit_program 'bye bye'
          fi
          done


          This assumes that exit_program takes care of exiting the program. If not, add exit afterwards. There is no need to test whether the ignore array is empty as the loop would not run a single iteration if it was.



          In the code above, "$ignore[@]" (note the double quotes) would expand to the list of usernames, each username individually quoted and protected from further word splitting and filename generation.



          Related:



          • The ShellCheck website


          For a version that is not specific to bash, but that would run in any POSIX-like shell:



          set -- 'user1' 'user2' 'user3'

          for u do
          if [ "$USER" = "$u" ]; then
          exit_program 'bye bye'
          fi
          done


          This uses the list of positional parameters as the list of usernames to ignore instead of an array.







          share|improve this answer















          share|improve this answer



          share|improve this answer








          edited 8 hours ago


























          answered 12 hours ago









          Kusalananda

          100k13199310




          100k13199310






















              up vote
              3
              down vote













              grep solution



              Use the "-w" feature of grep, to match a word.
              Daresay it won't work on older grep implementations, such as Solaris, AIX etc.



              echo $IGNORE_USER | grep -qw $USER && exit_program 'bye bye'


              Try it online!



              bash internal solution



              Go entirely bash, and don't rely on grep.



              bash doesn't allow a construct of =~ regex unless you run shopt -s compat31 first. So by using the =~ $(echo regex) we can overcome this. We use double quotes in this example, so that $USER gets expanded, and in so doing we need to escape out the b to be \b.



              [[ $IGNORE_USER =~ $(echo "\b$USER\b") ]] && exit_program 'bye bye'


              Try it online!






              share|improve this answer



























                up vote
                3
                down vote













                grep solution



                Use the "-w" feature of grep, to match a word.
                Daresay it won't work on older grep implementations, such as Solaris, AIX etc.



                echo $IGNORE_USER | grep -qw $USER && exit_program 'bye bye'


                Try it online!



                bash internal solution



                Go entirely bash, and don't rely on grep.



                bash doesn't allow a construct of =~ regex unless you run shopt -s compat31 first. So by using the =~ $(echo regex) we can overcome this. We use double quotes in this example, so that $USER gets expanded, and in so doing we need to escape out the b to be \b.



                [[ $IGNORE_USER =~ $(echo "\b$USER\b") ]] && exit_program 'bye bye'


                Try it online!






                share|improve this answer

























                  up vote
                  3
                  down vote










                  up vote
                  3
                  down vote









                  grep solution



                  Use the "-w" feature of grep, to match a word.
                  Daresay it won't work on older grep implementations, such as Solaris, AIX etc.



                  echo $IGNORE_USER | grep -qw $USER && exit_program 'bye bye'


                  Try it online!



                  bash internal solution



                  Go entirely bash, and don't rely on grep.



                  bash doesn't allow a construct of =~ regex unless you run shopt -s compat31 first. So by using the =~ $(echo regex) we can overcome this. We use double quotes in this example, so that $USER gets expanded, and in so doing we need to escape out the b to be \b.



                  [[ $IGNORE_USER =~ $(echo "\b$USER\b") ]] && exit_program 'bye bye'


                  Try it online!






                  share|improve this answer















                  grep solution



                  Use the "-w" feature of grep, to match a word.
                  Daresay it won't work on older grep implementations, such as Solaris, AIX etc.



                  echo $IGNORE_USER | grep -qw $USER && exit_program 'bye bye'


                  Try it online!



                  bash internal solution



                  Go entirely bash, and don't rely on grep.



                  bash doesn't allow a construct of =~ regex unless you run shopt -s compat31 first. So by using the =~ $(echo regex) we can overcome this. We use double quotes in this example, so that $USER gets expanded, and in so doing we need to escape out the b to be \b.



                  [[ $IGNORE_USER =~ $(echo "\b$USER\b") ]] && exit_program 'bye bye'


                  Try it online!







                  share|improve this answer















                  share|improve this answer



                  share|improve this answer








                  edited 6 hours ago


























                  answered 8 hours ago









                  steve

                  11.8k22046




                  11.8k22046






















                       

                      draft saved


                      draft discarded


























                       


                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function ()
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f460658%2fbash-how-to-improve-this-script%23new-answer', 'question_page');

                      );

                      Post as a guest













































































                      Comments

                      Popular posts from this blog

                      What is the equation of a 3D cone with generalised tilt?

                      Relationship between determinant of matrix and determinant of adjoint?

                      Color the edges and diagonals of a regular polygon