【问题标题】:Bash word splitting mechanismBash分词机制
【发布时间】:2018-04-14 05:53:52
【问题描述】:

我是 Bash 新手,我看到 Bash 会自动进行分词:

a="1  2     3 4"

如果我回显echo $a 的“a”,我得到1 2 3 4,它隐式地进行了分词。如果我遍历“a”,我分别得到 1、2、3 和 4。

我也从here 那里读到过

shell扫描参数扩展的结果,命令 代入和算术展开,没有发生在 双引号用于分词。

我还发现如果我有

b=$a;
echo "$b"

我会得到

"1 2 3 4"

所以,这是我的问题:分词何时完成?它会改变字符串本身吗?只有当我使用echofor(循环)时才生效?

更一般地说,bash 是如何处理它的?

【问题讨论】:

标签: string bash shell


【解决方案1】:

实际上有几轮分词。第一个是在解析命令行之前执行的,因此echo $a 被拆分为两个词echo$a。 (这就是为什么像a="echo foo | wc -l"; $a 这样的东西不执行管道;在扩展$a 之前解析完成)。该轮分词结束后,参数扩展产生2个字符串echo1 2 3 4。参数扩展产生的字符串然后会进行分词,因为它没有被引用,产生 4 个额外的词 1234

在for循环中,列表中的项目会被分词:

for b in $a; do

扩展(分词后产生forbin$a;do)到forforbin、@ 987654342@、;do。再次将参数扩展产生的字符串分词为1234

【讨论】:

    【解决方案2】:

    Bash 在解析脚本或命令行时作为下一个工作:

    1. 解析和词法分析
    2. 扩展
      1. 大括号扩展
      2. 标题扩展
      3. 变量扩展
      4. 算术和其他替换
      5. 命令替换
      6. 分词
      7. 文件名生成(通配符)
    3. 删除引号

    正如你所看到的,分词几乎在最后,所以在 e.g.算术扩展,但在文件名通配之前,删除引号是最后一步。

    【讨论】:

    • 对于不太熟悉 bash 的读者:虽然引号删除是最后一步,但它只会删除 在展开之前已经存在的引号。如果需要一些元编程,我们需要说sh -c "command with $variable"eval "command with $variable"
    【解决方案3】:

    阅读man bash。对于分配,它说

    所有值都经过波浪号扩展、参数和变量扩展、命令替换、算术扩展和引号删除 [ ... ] 不执行分词,但“$@”除外,如下面的特殊参数中所述。不执行路径名扩展。

    [[ ]] 条件下也不会发生分词:

    对[[和]]之间的单词不进行分词和路径名扩展

    【讨论】:

    • 非常感谢!但是 bash 是否在通话时进行分词而不是只进行一次?我的意思是 Bash 总是在它认为必要时执行拆分,而不是第一次执行然后保存它?如果它对同一个字符串进行多次拆分,我认为效率没有得到很好的考虑?
    • 如果你需要效率,不要使用bash。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-29
    • 2011-10-10
    • 1970-01-01
    • 1970-01-01
    • 2010-12-30
    相关资源
    最近更新 更多