引用时忽略参数

引用时忽略参数

我有一个包含 3 个文件的目录:file1以及file2以下 bash 脚本:

#!/bin/bash
set -e

Command="ls -1 -I file1"
echo "Command: $Command"

Files=`$Command`
echo "Files:"
echo $Files

结果正如人们所预料的那样。即被file1忽略并且不显示在列表中:

$ ./test.sh
Command: ls -1 -I file1
Files:
file2
test.sh

现在,如果我想支持忽略名称中带有空格的文件怎么办?我应该将文件名用引号引起来,对吗?出色地...

#!/bin/bash
set -e

Command="ls -1 -I 'file1'"
echo "Command: $Command"

Files=`$Command`
echo "Files:"
echo $Files

产量:

$ ./test.sh
Command: ls -1 -I 'file1'
Files:
file1
file2
test.sh

然而,直接在 bash 中计算相同的命令会产生正确的结果:

$ ls -1 -I 'file1'
file2
test.sh

这里发生了什么?添加引号似乎会使某些内容偏离轨道,但为什么呢?

用任何类似的命令替换命令都没有帮助:

Command="ls -1 -I \"file1\""
Command="ls -1 --ignore='file1'"

改变命令的评估也没有帮助:

Files=$($Command)
Files=$(`echo $Command`)

看来正确的行为只能通过引入eval

Files=$(eval $Command)
Files=`eval $Command`

我真的很想了解为什么要评估和执行,但不知何故,除非添加ls,否则引用的参数会被忽略。eval

答案1

因为报价删除如果引用字符本身已被引用,则不会应用于引用字符。

在:

Command="ls -1 -I 'file1'"

单引号'被双引号引用",因此它被视为字符串的一部分。您可以使用printfwith %q(in bash, kshand zsh) 来检查:

$ printf '%q\n' "$Command"
ls -1 -I 'file1'

如果直接在终端中运行,则单引号不会被引用,并且会被 shell 删除。

相关内容