它的工作原理与广告一致:
# example 1
#!/bin/bash
grep -ir 'hello world' .
这不是:
# example 2
#!/bin/bash
argumentString="-ir 'hello world'"
grep $argumentString .
尽管在第二个示例中,'hello world'
被引号括起来,grep将'hello
解释为一个参数,world'
解释为另一个参数,这意味着在本例中,'hello
将是搜索模式,world'
将是搜索路径。
同样,只有当参数从argumentString
变量展开时,才会发生这种情况。grep在第一个示例中将'hello world'
正确地解释为单个参数。
有人能解释为什么吗?是否有适当的方法来扩展字符串变量,从而保留每个字符的语法,以便shell命令能够正确地解释它?
当您将引号字符放入变量中时,它们只会变成纯文本(请参见http://mywiki.wooledge.org/BashFAQ/050;感谢@tripleee指出此链接)
相反,请尝试使用数组传递参数:
为什么
当字符串被展开时,它会被拆分成单词,但不会重新计算以查找特殊字符,如引号或美元符号或。。。这是自1978年左右的伯恩壳牌(Bourne shell)以来,壳牌一直“一贯”的做法。
修复
在
bash
中,使用数组保存参数:或者,如果勇敢/鲁莽,使用
eval
:另一方面,谨慎往往是勇敢的最好部分,与
eval
合作是一个谨慎胜于勇敢的地方。如果您不能完全控制eval
的字符串(如果命令字符串中有任何用户输入未经过严格验证),那么您将面临潜在的严重问题。注意,GNU Bash手册中的Shell Expansions描述了Bash的扩展序列。请特别注意第3.5.3节Shell参数扩展、第3.5.7节单词拆分和第3.5.9节引号删除。
在研究这个和相关的问题时,我很惊讶没有人提到使用显式子shell。对于bash和其他现代shell,可以显式地执行命令行。在bash中,它需要-c选项。
完全符合最初提问者的要求。这种技术有两个限制:
此外,此技术还处理重定向和管道,其他外壳也可以工作。您还可以使用bash内部命令以及在命令行中工作的任何其他命令,因为您实际上是要求子shell bash将其直接解释为命令行。这里有一个更复杂的例子,一个有点复杂的l s-l变体。
我用这种方法和参数数组构建了命令处理器。一般来说,这种方式编写和调试要容易得多,响应正在执行的命令也很简单。OTOH,param数组在确实有抽象的参数数组时工作得很好,而不是仅仅需要一个简单的命令变量。
相关问题 更多 >
编程相关推荐