1. 24
  1.  

  2. 4

    This says Bash, but isnt that POSIX sh?

    1. 2

      Yes, but Bash is compatible with POSIX sh and the author may not have known that the script was only using POSIX sh features.

    2. 3

      I like to think "$@" as keyword because it only works with that exact incantation. For example "-v $@" won’t work as it will be expanded to a single argument instead of a list of arguments.

      $* is not really useful in itself but can be used to indicate intent that no argument expansion should happen.

      For example:

      run() {
        echo "running $*"
        "$@"
      }
      
      run ls -la
      

      NOTE: this also works with bash arrays

      args=(a "b b" c)
      run "${args[@]}"
      
      1. 1

        A counter-point to the bernstein-chaining style is "${*@Q}"

        Sometimes some programs want to get the command as a string and this incantation allow you to escape the array properly back into bash.

        Eg:

        > echo "${args[*]@Q}"
        'a' 'b b' 'c'
        
        1. 1

          echo “${args[*]@Q}”

          It seems to work the same way with @ for me. As rule I never use anything like $* – it’s just easier to remember that way.

          bash-4.4$ args=(a "b b" c)
          bash-4.4$ echo "${args[*]@Q}"
          'a' 'b b' 'c'
          bash-4.4$ echo "${args[@]@Q}"                                                                                         
          'a' 'b b' 'c'
          

          (note: it doesn’t work at all in bash 4.3)

          1. 1

            yeah makes sense. those poor macOS users with their bash 3.0 are missing out on the good things.

      2. 3

        Yes, "$@" is the only thing I use and it’s a confusing syntax. Because "" usually means “don’t split” or “give me one string”, but "$@" gives you multiple strings, in contrast to “$*”. (And the other two possibilities are even more confusing.)

        It generalizes to arrays – you should use "${array[@]}" and not "${array[*]}". I’ve never found any reason to use the latter or any other variant:

        See Thirteen Incorrect Ways and Two Awkward Ways to Use Arrays

        In Oil, you can just write @myarray instead of "${myarray[@]}". And @ARGV is an alias for "$@". Let me know if it doesn’t make sense :)

        oil$ var myarray = @('has spaces' foo)
        oil$ var s = $'has\ttabs'
        
        oil$ echo $s
        has     tabs
        
        oil$ lines() { for x in @ARGV; do echo $x; done }
        
        oil$ lines @myarray $s
        has spaces
        foo
        has     tabs
        
        1. 1

          not “${array[*]}”. I’ve never found any reason to use the latter

          In Neovim we’re using it to:

          shellcheck doesn’t complain about this, but maybe there’s a better way? :)

          1. 3

            So the hilarious thing is that POSIX shell rules are even more complicated than what I laid out in that post. I’ve been meaning to write a followup Shell Has Context-Sensitive Evaluation to explain this.

            But it’s buried here under the bit about EvalWordToString and EvalWordSequence:

            https://github.com/oilshell/oil/wiki/Shell-WTFs

            So you can simply use "${array[@]}" in all those cases because it’s on the RHS of an assignment. But yeah if you want to use * for “clarity”, I won’t argue. It’s a matter of style. Shell syntax has nothing to do with its semantics :)

            $ a=('has spaces' foo)
            $ argv "${a[@]}"
            ['has spaces', 'foo']
            
            $ s1="${a[*]}"
            $ s2="${a[@]}"
            
            
            $ argv "$s1"
            ['has spaces foo']
            $ argv "$s2"
            ['has spaces foo']
            
        2. 2

          Nice. I see this as an interview question sometimes.

          1. 13

            Please don’t. This is a gotcha question about esoterica around bash. It doesn’t tell you much about the candidate other than if they read the right set of blog articles or experienced a particular kind of issue in the past.

            A better question would be “What quirks have most surprised you in bash?” Or something similar. It doesn’t assume any particular piece of trivia and a great candidate might even teach you something you didn’t know.

            1. 5

              I’ve seen it, not used it :)

              1. 3

                Ah, I completely misread your comment. Sorry about that.