AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / unix / 问题 / 421729
Accepted
Weijun Zhou
Weijun Zhou
Asked: 2018-02-04 16:49:55 +0800 CST2018-02-04 16:49:55 +0800 CST 2018-02-04 16:49:55 +0800 CST

bash 中的双引号如何匹配(配对)?

  • 772

我正在使用GNU bash 4.3.48. 考虑以下两个仅相差一个美元符号的命令。

命令 1:

echo "(echo " * ")"

命令 2:

echo "$(echo " * ")"

它们的输出分别是

(echo  test.txt ppcg.sh )

和

 * 

所以很明显在第一种情况下*是全局的,这意味着第一个引号与第二个引号形成一对,第三个和第四个形成另一个对。

在第二种情况下,*不是全局的,并且输出中正好有两个额外的空格,一个在星号之前,一个在星号之后,这意味着第二个引号与第三个引号一起出现,而第一个引号与第四个引号一起出现。

$()除了引号不与下一个匹配而是嵌套的构造之外,还有其他情况吗?这种行为是否有据可查,如果有,我在哪里可以找到相应的文档?

bash quoting
  • 2 2 个回答
  • 4137 Views

2 个回答

  • Voted
  1. Best Answer
    Michael Homer
    2018-02-04T17:49:09+08:002018-02-04T17:49:09+08:00

    任何可以在字符串中插入的嵌套结构都可以在其中包含更多的字符串:它们像新脚本一样被解析,直到结束标记,甚至可以嵌套多层深度。所有这些都以 . 开头$。所有这些都记录在 Bash 手册和 POSIX shell 命令语言规范的组合中。

    这些结构有几种情况:

    • $( ... )如您所见,用 替换命令。POSIX 指定此行为:

      使用该$(command)形式,从左括号到匹配的右括号的所有字符构成命令。任何有效的 shell 脚本都可以用于命令...

      引号是有效 shell 脚本的一部分,因此它们的正常含义是允许的。

    • 也使用 的命令替换`。
    • 高级参数替换实例的“word”元素,例如${parameter:-word}. “词”的定义是:

      被 shell 视为一个单元的字符序列

      - 包括引用的文本甚至混合引号a"b"c'd'e- 尽管扩展的实际行为比这更自由一些,例如${x:-hello world}也有效。

    • 用 进行算术扩展,$(( ... ))虽然它在那里基本上没用(但您也可以嵌套命令替换或变量扩展,然后在其中有用地使用引号)。POSIX 声明:

      表达式应被视为在双引号中,但表达式中的双引号没有被特殊处理。shell 应扩展表达式中的所有标记,以进行参数扩展、命令替换和引号删除。

      所以这种行为是明确要求的。这意味着echo "abc $((4 "*" 5))"算术,而不是通配符。

      请注意,旧式$[ ... ]算术扩展的处理方式不同:如果出现引号,则无论扩展是否被引用,引号都是错误的。这个表格根本没有记录,无论如何也不打算使用。

    • 特定于语言环境的翻译 with$"...",它实际上将"用作核心元素。$"被视为一个单元。

    还有一种您可能没想到的嵌套情况,不涉及引号,它带有大括号扩展:{a,b{c,d},e}扩展为“a bc bd e”。但是,不${x:-a{b,c}d}嵌套;它被视为参数替换,给出“ ”,后跟“ ”。这也记录在案:a{b,cd}

    当使用大括号时,匹配的结束大括号是第一个没有被反斜杠或带引号的字符串转义的'}',并且不在嵌入式算术扩展、命令替换或参数扩展中。


    作为一般规则,所有定界构造都独立于周围的上下文解析它们的主体(并且异常被视为错误)。本质上,在看到命令替换代码时,它只是要求解析器从主体中消耗它可以使用的东西,就好像它是一个新程序一样,然后在子解析器运行时$(检查预期的终止标记(未转义的)or )))是否出现}它可以消耗的东西。

    如果您考虑递归下降解析器的功能,那只是对基本情况的简单递归。一旦你有了字符串插值,它实际上比其他方式更容易做到。不管底层的解析技术如何,支持这些结构的 shell 都会给出相同的结果。

    您可以通过这些结构尽可能深入地嵌套引用,它会按预期工作。看到中间的引用不会让任何地方感到困惑;相反,这将是内部上下文中新引用字符串的开始。

    • 15
  2. user232326
    2018-02-04T20:22:35+08:002018-02-04T20:22:35+08:00

    printf也许用(而不是)查看两个示例echo会有所帮助:

    $ printf '<%s> ' "(echo " * ")"; echo
    <(echo > <test.txt> <ppcg.sh> <file1> <file2> <file3> <)>
    

    它打印(echo (第一个词,包括尾随空格)、一些文件和结束词)。
    括号只是引用字符串的一部分(echo 。
    星号(现在不加引号,因为两个双引号是配对的)作为一个 glob 扩展为匹配文件的列表。
    然后是右括号。

    但是,您的第二个命令的工作方式如下:

    $ printf '<%s> ' "$(echo " * ")" ; echo
    < * >
    

    $开始命令替换。这开始了一个新的报价。
    星号是带引号的" * ",这就是命令(这里是命令而不是带引号的字符串)echo输出的内容。最后,printf重新格式化*并将其打印为< * >.

    • 3

相关问题

  • 通过命令的标准输出以编程方式导出环境变量[重复]

  • 从文本文件传递变量的奇怪问题

  • 虽然行读取保持转义空间?

  • `tee` 和 `bash` 进程替换顺序

  • 运行一个非常慢的脚本直到它成功

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    如何将 GPG 私钥和公钥导出到文件

    • 4 个回答
  • Marko Smith

    ssh 无法协商:“找不到匹配的密码”,正在拒绝 cbc

    • 4 个回答
  • Marko Smith

    我们如何运行存储在变量中的命令?

    • 5 个回答
  • Marko Smith

    如何配置 systemd-resolved 和 systemd-networkd 以使用本地 DNS 服务器来解析本地域和远程 DNS 服务器来解析远程域?

    • 3 个回答
  • Marko Smith

    如何卸载内核模块“nvidia-drm”?

    • 13 个回答
  • Marko Smith

    dist-upgrade 后 Kali Linux 中的 apt-get update 错误 [重复]

    • 2 个回答
  • Marko Smith

    如何从 systemctl 服务日志中查看最新的 x 行

    • 5 个回答
  • Marko Smith

    Nano - 跳转到文件末尾

    • 8 个回答
  • Marko Smith

    grub 错误:你需要先加载内核

    • 4 个回答
  • Marko Smith

    如何下载软件包而不是使用 apt-get 命令安装它?

    • 7 个回答
  • Martin Hope
    rocky 如何将 GPG 私钥和公钥导出到文件 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Wong Jia Hau ssh-add 返回:“连接代理时出错:没有这样的文件或目录” 2018-08-24 23:28:13 +0800 CST
  • Martin Hope
    Evan Carroll systemctl 状态显示:“状态:降级” 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim 我们如何运行存储在变量中的命令? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S 为什么 /dev/null 是一个文件?为什么它的功能不作为一个简单的程序来实现? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 如何从 systemctl 服务日志中查看最新的 x 行 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - 跳转到文件末尾 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla 为什么真假这么大? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis 在一个巨大的(70GB)、一行、文本文件中替换字符串 2017-12-30 06:58:33 +0800 CST
  • Martin Hope
    Bagas Sanjaya 为什么 Linux 使用 LF 作为换行符? 2017-12-20 05:48:21 +0800 CST

热门标签

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve