Bash quoted array expansion

前端 未结 6 948
借酒劲吻你
借酒劲吻你 2021-01-31 02:57

WHen I write a bash program I typically construct calls like follows:

declare -a mycmd=( command.ext \"arg1 with space\" arg2 thing etc )

\"${mycmd[@]}\" || ech         


        
6条回答
  •  夕颜
    夕颜 (楼主)
    2021-01-31 03:15

    Your problem is with echo. It is getting the correct number of parameters, with some parameters containing spaces, but it's output loses the distinction of spaces between parameters and spaces within parameters.

    Instead, you can use printf(1) to output the parameters and always include quotes, making use of printf's feature that applies the format string successively to parameters when there are more parameters than format specifiers in the format string:

    echo "Failed: foo:" $(printf "'%s' " "${mycmd[@]}")
    

    That will put single quotes around each argument, even if it is not needed:

    Failed: foo: 'command.ext' 'arg1 with space' 'arg2' 'thing' 'etc'
    

    I've used single quotes to ensure that other shell metacharacters are not mishandled. This will work for all characters except single quote itself - i.e. if you have a parameter containing a single quote, the output from the above command will not cut and paste correctly. This is likely the closest you will get without getting messy.

    Edit: Almost 5 years later and since I answered this question, bash 4.4 has been released. This has the "${var@Q}" expansion which quotes the variable such that it can be parsed back by bash.

    This simplifies this answer to:

    echo "Failed: foo: " "${mycmd[@]@Q}"
    

    This will correctly handle single quotes in an argument, which my earlier version did not.

提交回复
热议问题