为了账号安全,请及时绑定邮箱和手机立即绑定

为什么shell忽略通过变量传递给它的参数中的引号?

为什么shell忽略通过变量传递给它的参数中的引号?

守着星空守着你 2019-06-05 16:27:02
为什么shell忽略通过变量传递给它的参数中的引号?这项工作如广告所示:# example 1#!/bin/bashgrep -ir 'hello world' .这并不是:# example 2#!/bin/bashargumentString="-ir 'hello world'"grep $argumentString .尽管'hello world'在第二个示例中用引号括起来,grep解释'hello作为一个论点world'作为另一种,这意味着,在这种情况下,'hello将是搜索模式world'将是搜索路径。同样,只有当参数从argumentString变量。grep正确解释'hello world'作为第一个例子中的一个参数。有人能解释一下为什么吗?是否有适当的方法来展开字符串变量,以保留每个字符的语法,从而使其被shell命令正确地解释?
查看完整描述

3 回答

?
胡说叔叔

TA贡献1804条经验 获得超8个赞

为什么

当字符串被展开时,它被分割成单词,但是它不会被重新计算以找到特殊的字符,如引号或美元符号或.这是壳牌自1978年伯恩壳牌(Bourne Shell)前后一直表现出来的方式。

固定

在……里面bash,使用数组保存参数:

argumentArray=(-ir 'hello world')grep "${argumentArray[@]}" .

或者,如果勇敢/鲁莽,就用eval:

argumentString="-ir 'hello world'"eval "grep $argumentString ."

另一方面,谨慎常常是勇气的更好的部分,并与之合作。eval是一个谨慎胜于勇敢的地方。如果没有完全控制字符串,则为evalid(如果命令字符串中有任何用户输入未经严格验证),那么您将面临潜在的严重问题。

请注意,Bash的展开顺序在壳展开在GNU手册里。请特别注意3.5.3 Shell参数展开、3.5.7字拆分和3.5.9引号删除部分。


查看完整回答
反对 回复 2019-06-05
?
不负相思意

TA贡献1777条经验 获得超10个赞

在查看这个问题和相关问题时,我感到惊讶的是,没有人使用显式的子shell。对于bash和其他现代shell,可以显式执行命令行。在bash中,它需要-c选项。

argumentString="-ir 'hello world'"bash -c "grep $argumentString ."

完全符合发问者的要求。这种技术有两个限制:

  1. 只能在命令或参数字符串中使用单引号。
  2. 命令只有导出的环境变量可用。

此外,这种技术处理重定向和管道,以及其他搁置工作。您还可以使用bash内部命令以及在命令行中工作的任何其他命令,因为您实际上是要求subshell bash将其直接解释为命令行。这里有一个更复杂的例子,一个有点毫无道理的复杂的ls-l变体。

cmd="prefix=`pwd` && ls | xargs -n 1 echo \'In $prefix:\'"bash -c "$cmd"

我已经用这种方式和参数数组构建了命令处理器。一般来说,这种方式是编写和调试更容易,而且响应正在执行的命令也很简单。OTOH,Param数组在您确实有抽象的参数数组时工作得很好,而不是只想要一个简单的命令变体。


查看完整回答
反对 回复 2019-06-05
  • 3 回答
  • 0 关注
  • 1195 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信