命令替换 - 单引号和空格

命令替换 - 单引号和空格

如何使命令替换传递由空格分隔的单引号 POSIX 路径列表?

command1 $(command2)
command1 '/path/to/file 1' '/path/to/file 2' '/path/to/file 3'

我如何追踪扩展?

答案1

您可以使用 来准确查看正在运行的命令set -x。一个相当愚蠢的例子:

$ echo $(echo "foo 'bar baz' taz\\ jaz")
foo 'bar baz' taz\ jaz

会给:

++ echo 'foo '\''bar baz'\'' taz\ jaz'
+ echo foo ''\''bar' 'baz'\''' 'taz\' jaz
foo 'bar baz' taz\ jaz

由于所有转义,这有点难以阅读。例如第二个词:

  1. ''变得一无所有。
  2. \'变成单引号 ( ')
  3. 'bar'变成bar

因此该参数作为 传递'bar。您可以使用类似的内容进行确认(假设您安装了 Data::Dump,不幸的是,这不是默认设置)请注意,$(echo…已将其逐字复制到 perl 行:

$ perl -MData::Dump=pp -E 'pp @ARGV' $(echo "foo 'bar baz' taz\\ jaz")
("foo", "'bar", "baz'", "taz\\", "jaz")

这里发生的是 bash 正在进行分词(基于 off $IFS),而不是参数解析。因此,不幸的是,您可能必须使用eval并处理由此带来的所有风险。

$ eval "echo $(echo "foo 'bar baz' taz\\ jaz")"
foo bar baz taz jaz

(另外,我会注意到,如果你可以让你的命令生成其输出作为名称列表,用 NUL 分隔,那就是简单的处理使用xargs -0和进一步,完全安全)。

答案2

您很少能拥有可理解格式的文件列表xargs。所以跑

command1 | xargs command2

请注意,在某些 UNIX 变体上,如果 的输出很大,由于命令行长度限制,command1将无法使用所有文件名运行。command2使用的缺点xargs是它会多次运行命令而不是正确报告错误。您可以使用 检查命令行长度限制getconf ARG_MAX

答案3

尝试这样的事情:-

path1="/etc/passwd"
path2="/var/log/secure"

[root@localhost base_filters]# ls -l "$path1" "$path2"
-rw-r--r--. 1 root root 1876 Mar 10 22:15 /etc/passwd
-rw-------. 1 root root 2408 Apr  5 23:09 /var/log/secure

答案4

尝试使用 IFS 变量,这样空间就不会影响您的脚本。我会将 IFS 存储在变量中,并在完成脚本操作后恢复 IFS。

相关内容