Concatenate all arguments and wrap them with double quotes

前端 未结 6 1477
广开言路
广开言路 2020-12-15 05:52
function foo() {
A=$@...
echo $A
}

foo bla \"hello ppl\"

I would like the output to be:
\"bla\" \"hello ppl\"

What do I need to do in

6条回答
  •  悲&欢浪女
    2020-12-15 06:38

    The only solution at this time that respects backslashes and quotes inside the argument:

    $ concatenate() { printf "%q"" " "$@"; echo ""; }
    $ concatenate arg1 "arg2" "weird arg3\\\\\\bbut\" legal!"
    arg1 arg2 weird\ arg3\\\\\\bbut\"\ legal\!
    

    Notice the "%q"" "

    %q ARGUMENT is printed in a format that can be reused as shell input, escaping non-printable characters with the proposed POSIX $'' syntax.

    Special characters (\, \b backspace, ...) will indeed be interpreted by the receiving program, even if not displayed interpreted in the terminal output.

    Let's test:

    # display.sh: Basic script to display the first 3 arguments passed
    echo -e '#!/bin/bash'"\n"'echo -e "\$1=""$1"; echo -e "\$2=""$2"; echo -e "\$3=""$3"; sleep 2;' > display.sh
    sudo chmod 755 display.sh
    
    # Function to concatenate arguments as $ARGS
    # and "evalutate" the command display.sh $ARGS
    test_bash() { ARGS=$(concatenate "$@"); bash -c "./display.sh ""$ARGS"; }
    
    # Test: Output is identical whatever the special characters
    ./display.sh arg1 arg2 arg3
    test_bash    arg1 arg2 arg3
    

    More complicate test:

    ./display.sh arg1 "arg2-1:Y\b-2:Y\\b-3:Y\\\b-4:Y\\\\b-5:Y\\\\\b-6:Y\\\\\\b" "arg3-XY\bZ-\"-1:\-2:\\-3:\\\-4:\\\\-5:\\\\\-6:\\\\\\-"
    test_bash    arg1 "arg2-1:Y\b-2:Y\\b-3:Y\\\b-4:Y\\\\b-5:Y\\\\\b-6:Y\\\\\\b" "arg3-XY\bZ-\"-1:\-2:\\-3:\\\-4:\\\\-5:\\\\\-6:\\\\\\-"
    

    In display.sh, we are using echo -e instead of just echo or printf in order to interpret the special characters. This is only representative if your called program interprets them.

    -e enable interpretation of backslash escapes

    If -e is in effect, the following sequences are recognized:

    • \ backslash
    • \a alert (BEL)
    • \b backspace
    • Etc.

    NB: \b is the backspace character, so it erases Y in the example.

    Note that this example is not to be reproduced in real code:

    • It is very uncommon to concatenate arguments, always use positional parameter when possible.
    • bash -c and screen -X DO accept several arguments so there's no need to use concatenation: see Can't seem to use bash -c option with arguments after the -c option string). Just beware of passing something for $0 when using bash -c.

    Thanks to the accepted answer and Danny Hong answer in "How to escape double quote inside a double quote?"

提交回复
热议问题