Preserving quotes in bash function parameters

后端 未结 8 781
天涯浪人
天涯浪人 2020-12-05 05:13

What I\'d like to do is take, as an input to a function, a line that may include quotes (single or double) and echo that line exactly as it was provided to the function. For

8条回答
  •  [愿得一人]
    2020-12-05 05:29

    If one's shell does not support pattern substitution, i.e. ${param/pattern/string} then the following sed expression can be used to safely quote any string such that it will eval into a single parameter again:

    sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/'/"
    

    Combining this with printf it is possible to write a little function that will take any list of strings produced by filename expansion or "$@" and turn it into something that can be safely passed to eval to expand it into arguments for another command while safely preserving parameter separation.

    # Usage: quotedlist=$(shell_quote args...)
    #
    # e.g.:  quotedlist=$(shell_quote *.pdf)    # filenames with spaces
    #
    # or:    quotedlist=$(shell_quote "$@")
    #
    # After building up a quoted list, use it by evaling it inside
    # double quotes, like this:
    #
    #   eval "set -- $quotedlist"
    #   for str in "$@"; do
    #       # fiddle "${str}"
    #   done
    #
    # or like this:
    #
    #   eval "\$a_command $quotedlist \$another_parameter"
    #
    shell_quote()
    {
        local result=''
        local arg
        for arg in "$@" ; do
    
            # Append a space to our result, if necessary
            #
            result=${result}${result:+ }
    
            # Convert each embedded ' to \' , then insert ' at the
            # beginning of the line, and append ' at the end of
            # the line.
            #
            result=${result}$(printf "%s\n" "$arg" | \
                sed -e "s/'/'\\\\''/g" -e "1s/^/'/" -e "\$s/\$/'/")
        done
    
        # use printf(1) instead of echo to avoid weird "echo"
        # implementations.
        #
        printf "%s\n" "$result"
    }
    

    It may be easier (and maybe safer, i.e. avoid eval) in some situations to use an "impossible" character as the field separator and then use IFS to control expansion of the value again.

提交回复
热议问题