Concatenate all arguments and wrap them with double quotes

前端 未结 6 1455
广开言路
广开言路 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:26

    No loop required:

    foo() { local saveIFS=$IFS; local IFS='"'; local a="${*/#/ \"}"; echo "$a"\"; IFS=$saveIFS; }
    

    Saving IFS isn't necessary in this simple example, especially restoring it right before the function exits, due to the fact that local is used. However, I included it in case other things are going into the function that a changed IFS might affect.

    Example run:

    $ foo a bcd "efg hij" k "lll mmm nnn " ooo "   ppp   qqq   " rrr\ sss
     "a" "bcd" "efg hij" "k" "lll mmm nnn " "ooo" "   ppp   qqq   " "rrr sss"
    
    0 讨论(0)
  • 2020-12-15 06:36

    Use parameter substitution to add " as prefix and suffix:

    function foo() {
        A=("${@/#/\"}")
        A=("${A[@]/%/\"}")
        echo -e "${A[@]}"
    }
    
    foo bla "hello ppl" kkk 'ss ss'
    

    Output

    "bla" "hello ppl" "kkk" "ss ss"
    
    0 讨论(0)
  • 2020-12-15 06:37

    @msw has the right idea (up in the comments on the question). However, another idea to print arguments with quotes: use the implicit iteration of printf:

    foo() { printf '"%s" ' "$@"; echo ""; }
    
    foo bla "hello ppl"
    # => "bla" "hello ppl"
    
    0 讨论(0)
  • 2020-12-15 06:38

    You can use "$@" to treat each parameter as, well, a separate parameter, and then loop over each parameter:

    function foo() {
    for i in "$@"
    do
        echo -n \"$i\"" "
    done
    echo
    }
    
    foo bla "hello ppl"
    
    0 讨论(0)
  • 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?"

    0 讨论(0)
  • 2020-12-15 06:53

    ninjalj had the right idea, but the use of quotes was odd, in part because what the OP is asking for is not really the best output format for many shell tasks. Actually, I can't figure out what the intended task is, but:

    function quote_args {
       for i ; do
          echo \""$i"\"
       done
    }
    

    puts its quoted arguments one per line which is usually the best way to feed other programs. You do get output in a form you didn't ask for:

    $ quote_args this is\ a "test really"
    "this"
    "is a"
    "test really"
    

    but it can be easily converted and this is the idiom that most shell invocations would prefer:

    $ echo `quote_args this is\ a "test really"`
    "this" "is a" "test really"
    

    but unless it is going through another eval pass, the extra quotes will probably screw things up. That is, ls "is a file" will list the file is a file while

    $ ls `quote_args is\ a\ file`
    

    will try to list "is, a, and file" which you probably don't want.

    0 讨论(0)
提交回复
热议问题