shell在bash中引用引号

时间:2013-07-14 09:00:00

标签: bash escaping printf

我想实现一个bash函数,它将其参数作为命令运行,而(可能选择)之前打印命令。想想安装脚本或测试运行器脚本。

只需使用

function run () {
    echo "Running $@"
    "$@"
}

不允许我区分来自run foo arg1 arg2run foo "arg1 arg2"的来电,因此我需要正确地撤销参数。

到目前为止,我最好的拍摄是

function run () {
    echo -n "Running"
    printf " %q" "$@"
    echo
    "$@"
}

哪个有效:

$ run echo "one_argument" "second argument" argument\"with\'quotes
Running echo one_argument second\ argument argument\"with\'quotes
one_argument second argument argument"with'quotes

但不是很优雅。如何实现

的输出
$ run echo "one_argument" "second argument" argument\"with\'quotes
Running echo one_argument "second argument" "argument\"with'quotes"
one_argument second argument argument"with'quotes

即。如何让printf在需要引用的参数周围加上引号,并在其中正确地转义引号,以便输出可以正确复制?

2 个答案:

答案 0 :(得分:3)

这将引用一切:

run() {
    printf "Running:"
    for arg; do 
        printf ' "%s"' "${arg//\"/\\\"}"
    done
    echo
    "$@"
}
run echo "one_argument" "second argument" argument\"with\'quotes
Running: "echo" "one_argument" "second argument" "argument\"with'quotes"
one_argument second argument argument"with'quotes

此版本仅引用包含双引号或空格的参数:

run() {
    local fmt arg
    printf "Running:"
    for arg; do
        [[ $arg == *[\"[:space:]]* ]] && fmt=' "%s"' || fmt=" %s" 
        printf "$fmt" "${arg//\"/\\\"}"
    done
    echo
    "$@"
}
run echo "one_argument" "second argument" argument\"with\'quotes
Running: echo one_argument "second argument" "argument\"with'quotes"
one_argument second argument argument"with'quotes

答案 1 :(得分:2)

我认为没有一个优雅的解决方案可以满足您的需求,因为"$@"bash在任何命令看到之前由#!/bin/bash function run() { echo -n "Running:" for arg in "$@"; do arg="$(sed 's/"/\\&/g' <<<$arg)" [[ $arg =~ [[:space:]\\\'] ]] && arg=\"arg\" echo -n " $arg" done echo "" "$@" } run "$@" 处理。您必须手动重新构建命令行:

$ ./test.sh echo arg1 "arg 2" "arg3\"with'other\'\nstuff"
Running: echo arg1 "arg 2" "arg3\"with'other\'\nstuff"
arg1 arg 2 arg3"with'other\'\nstuff

输出:

bash

请注意,在某些极端情况下,您将无法获得确切的输入命令行。当你传递$ ./test.sh echo foo'bar'baz Running: echo foobarbaz foobarbaz $ ./test.sh echo "foo\\bar" Running: echo "foo\bar" foobar在传递它们之前扩展的参数时会发生这种情况,例如:

{{1}}