bash中带引号的Shell引用

bash中带引号的Shell引用,bash,escaping,printf,Bash,Escaping,Printf,我想实现一个bash函数,该函数将其参数作为命令运行,同时(可能是可选的)在之前打印命令。请考虑安装脚本或测试运行程序脚本 只是使用 function run () { echo "Running $@" "$@" } 不允许我将调用与运行foo arg1 arg2和运行foo“arg1 arg2”区分开来,因此我需要正确地转义参数 到目前为止,我最好的机会是 function run () { echo -n "Running" printf " %q" "$

我想实现一个bash函数,该函数将其参数作为命令运行,同时(可能是可选的)在之前打印命令。请考虑安装脚本或测试运行程序脚本

只是使用

function run () {
    echo "Running $@"
    "$@"
}
不允许我将调用与
运行foo arg1 arg2
运行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

i、 e.我如何才能使
printf
在需要引用的参数周围加上引号,并正确地转义其中的引号,以便输出可以正确地复制粘贴?

我认为没有一个优雅的解决方案可以满足您的需要,因为
“$@”
在任何命令看到它之前由
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 "$@"

我认为没有一个优雅的解决方案可以满足您的需求,因为在任何命令看到它之前,
“$@”
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 "$@"

这将引用所有内容:

run() {
    printf "Running:"
    for arg; do 
        printf ' "%s"' "${arg//\"/\\\"}"
    done
    echo
    "$@"
}
run echo "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

这将引用所有内容:

run() {
    printf "Running:"
    for arg; do 
        printf ' "%s"' "${arg//\"/\\\"}"
    done
    echo
    "$@"
}
run echo "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

你能不能把所有的论点都用引号括起来,而不仅仅是那些需要的论点?您只需在所有参数周围转义双引号,如下所示:tldp.org/LDP/Bash-初学者-Guide/html/sect_03_03.htmlh这将是丑陋的,如果参数包含引号,则不正确。用于调试输出,虽然没有那么严重,但我仍然希望输出是正确的。啊,我明白了。很抱歉,我对BASH的了解还不足以帮助你克服这个问题。看看这个:在参数中也没有转义引号。我想我应该详细说明我的问题。你能不能在所有的论点周围加上引号,而不仅仅是那些需要的论点?您只需在所有参数周围转义双引号,如下所示:tldp.org/LDP/Bash-初学者-Guide/html/sect_03_03.htmlh这将是丑陋的,如果参数包含引号,则不正确。用于调试输出,虽然没有那么严重,但我仍然希望输出是正确的。啊,我明白了。很抱歉,我对BASH的了解还不足以帮助你克服这个问题。看看这个:在参数中也没有转义引号。我想我应该详细说明我的问题。这看起来与评论中@MohammadJavadNaderi的链接非常相似;它似乎无法处理引用特殊字符,例如
本身。您不能
将参数移开--打印后您将无法执行命令!此外,正则表达式将匹配字符{“a”、“c”、“e”、“p”、“s”、“:”}中的一个--您需要
[:space:]
@glennjackman这就是我因测试不足而得到的结果。感谢大家的提醒。修复了。这看起来与评论中的@MohammadJavadNaderi链接非常相似;它似乎无法处理引用特殊字符,如
本身。您不能
参数移开--打印后将无法执行该命令!此外,正则表达式将匹配字符{“a”、“c”、“e”、“p”、“s”和“:”}中的一个--您需要
[[:space:]
@glennjackman这是我在测试不足时得到的结果。谢谢你的提醒。固定的。
Running: echo one_argument "second argument" "argument\"with'quotes"
one_argument second argument argument"with'quotes