Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/shell/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
命令替换中的bash变量替换_Bash_Shell - Fatal编程技术网

命令替换中的bash变量替换

命令替换中的bash变量替换,bash,shell,Bash,Shell,我想做如下事情: #!/bin/bash cmd="find . -name '*.sh'" echo $($cmd) 我所期望的是,它将显示当前目录中的所有shell脚本文件,但什么也没有发生 我知道我可以用eval解决这个问题 所以我的问题是为什么命令替换在这里不起作用,就这个问题而言,$(…)和eval之间有什么区别?既然您已经在双引号中包含了patter*.sh,那么就不需要单引号来保护模式,因此,单引号是模式的一部分 您可以尝试使用数组将*.sh保留为引号,直到将其传递给命令替换:

我想做如下事情:

#!/bin/bash

cmd="find . -name '*.sh'"
echo $($cmd)
我所期望的是,它将显示当前目录中的所有shell脚本文件,但什么也没有发生

我知道我可以用eval解决这个问题


所以我的问题是为什么命令替换在这里不起作用,就这个问题而言,$(…)和eval之间有什么区别?

既然您已经在双引号中包含了patter
*.sh
,那么就不需要单引号来保护模式,因此,单引号是模式的一部分

您可以尝试使用数组将
*.sh
保留为引号,直到将其传递给命令替换:

cmd=(find . -name '*.sh')
echo $("${cmd[@]}")
我不知道是否有一种简单的方法可以在不扩展模式的情况下将原始字符串转换为数组

更新:这还不算太糟,但是如果可以的话,直接创建数组可能更好

cmd="find . -name *.sh"
set -f
cmd=($cmd)
set +f
echo $("${cmd[@]}")

命令替换在这里起作用。只是你的报价有误。您的脚本只能找到一个文件名!这个带单引号和星号的:

'*.sh'
您可以通过以下命令创建此类非常规文件并对其进行测试:

touch "'*.sh'"
bash中的引号与其他编程语言中的引号不同。查看本文中的详细信息:

您需要的是以下引用:

cmd="find . -name *.sh"
echo $($cmd)

当您使用
echo$($cmd)
语法时,它基本上等同于将
$cmd
放在它自己的行中。问题在于bash希望在命令运行之前插入通配符的方式。防止这种情况发生的方法是,在脚本中取消引用包含
*
字符的变量时,再次将其置于引号中

但是如果你把整个命令
find-在一个变量中命名“*.sh”
,然后用`echo$(“$cmd”)引用它,shell将解释这意味着整行是要执行的文件,您将得到一个file not found错误

所以这实际上取决于你在变量中真正需要什么,以及可以从中提取什么。如果您需要变量中的程序,这将起作用:

#!/bin/bash

cmd='/usr/bin/find'
$cmd . -name "*.sh" -maxdepth 1
这将查找当前工作目录中以
.sh
结尾的所有文件,而无需shell插入通配符

如果需要将模式置于变量中,可以使用:

#!/bin/bash

pattern="*.sh"
/usr/bin/find . -name "$pattern" -maxdepth 1

但是如果你把整个事情放在一个变量里,你就不会得到你所期望的。希望这有帮助。如果bash大师知道我遗漏了什么,我很乐意听到。

这是我最初发布的内容。问题是模式在执行命令之前会展开,因此您只能找到模式匹配的文件(即,您无法从子目录中获取任何文件)。切普纳:我现在看到您的答案包含了我的部分内容。我被你建议的数组误导了,没有仔细阅读你的帖子。事实上,我喜欢数组技巧!如果要将搜索仅限于当前工作目录,请记住将
-maxdepth 1
添加到
find
。除非使用其他谓词优化搜索,否则使用
-maxdepth 1
的给定find命令(我认为)相当于简单的模式匹配,我在没有
-maxdepth 1
的情况下运行了这个脚本,它遍历了目录,在下面找到了更多的shell脚本。使用它,它将搜索范围限制在当前工作目录中,这就是我对其他谓词的意思
*.sh
还将匹配当前目录中的所有shell脚本,但不允许您根据文件类型、访问时间、文件大小或
find
提供的其他属性进行筛选。
#!/bin/bash

pattern="*.sh"
/usr/bin/find . -name "$pattern" -maxdepth 1