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 / 问题 / 410983
Accepted
Wildcard
Wildcard
Asked: 2017-12-15 21:58:06 +0800 CST2017-12-15 21:58:06 +0800 CST 2017-12-15 21:58:06 +0800 CST

Bash 如何处理参数扩展的字符串替换部分中的引用?

  • 772

有什么一致的逻辑吗?

some-command "${somevariable//some pattern/'how does this get parsed?'}"

我在下面发布了一些结论和原始测试作为“答案”,但无论如何它们都不是完整的答案。Bash 手册页对该主题保持沉默。

bash quoting
  • 3 3 个回答
  • 2414 Views

3 个回答

  • Voted
  1. Best Answer
    ilkkachu
    2017-12-16T04:00:24+08:002017-12-16T04:00:24+08:00

    正如评论中所讨论的,这似乎在 Bash 版本之间发生了变化。我认为这是bash-4.3-alpha(changelog)中的相关更改:

    Z Z。当使用模式替换词扩展时,bash 现在通过引号删除来运行替换字符串,因为它允许该字符串中的引号充当转义字符。这不是向后兼容的,因此可以通过将 bash 兼容模式设置为 4.2 来禁用它。

    shopt -s compat42以及(在线手册)的描述:

    compat42
    如果设置,bash 不会使用引号删除处理模式替换词扩展中的替换字符串。

    引用单引号的例子:

    $ s=abc\'def; echo "'${s//\'/\'\\\'\'}'"
    'abc'\''def'
    
    $ shopt -s compat42
    $ s=abc\'def; echo "'${s//\'/\'\\\'\'}'"
    'abc\'\\'\'def'
    
    $ bash --version | head -1
    GNU bash, version 4.4.12(1)-release (x86_64-pc-linux-gnu)
    

    解决方法:将替换字符串放在变量中,并且不要在替换中使用引号:

    $ shopt -s compat42
    $ qq="'\''"; s=abc\'def; echo "'${s//\'/$qq}'";
    'abc'\''def'
    $ qq="'\''"; s=abc\'def; echo "'${s//\'/"$qq"}'";
    'abc"'\''"def'
    

    有趣的是,如果扩展是unquoted,那么在所有版本中替换后引号都会被删除。那就是s=abc; echo ${s/b/""}打印ac。这当然不会发生在其他扩展中,例如s='a""c' ; echo ${s%x}输出a""c。

    • 7
  2. Wildcard
    2017-12-15T21:58:06+08:002017-12-15T21:58:06+08:00

    逆向工程的一般规则:

    • 报价必须耦合(完成)
    • 报价被保留(包含在实际替换中)
    • 如果反斜杠出现在任意字母之前,则保留它们
    • 如果转义单引号,则保留反斜杠
    • 即使在单引号内,反斜杠反斜杠序列也会减少为一个反斜杠
    • 您不能在单引号内转义单引号
    • 参数扩展在单引号内的工作方式与在外相同
    • 如果使用反斜杠转义美元符号,则按字面意思保留美元符号并删除反斜杠

    和一个结论:

    • 绝对没有办法'\''通过参数扩展产生文字序列作为替换。
    • 但是,很容易产生文字序列"'\''"作为替换。

    接下来是一些原始测试。

    [vagrant@localhost ~]$ echo "$0"
    -bash
    [vagrant@localhost ~]$ echo "${0//a/x}"
    -bxsh
    [vagrant@localhost ~]$ echo "${0//a/some long string  with spaces}"
    -bsome long string  with spacessh
    [vagrant@localhost ~]$ echo "${0//a/"quoted string"}"
    -b"quoted string"sh
    [vagrant@localhost ~]$ echo "${0//a/"unfinished quote}"
    > wat
    > }"
    -b"unfinished quote}"
    wat
    sh
    [vagrant@localhost ~]$ echo "${0//a/\"escaped quote}"
    -b"escaped quotesh
    [vagrant@localhost ~]$ echo "${0//a/\\escaped escape}"
    -b\escaped escapesh
    [vagrant@localhost ~]$ echo "${0//a/\'escaped single quote}"
    -b\'escaped single quotesh
    [vagrant@localhost ~]$ echo "${0//a/''}"
    -b''sh
    [vagrant@localhost ~]$ echo "${0//a/''''}"
    -b''''sh
    [vagrant@localhost ~]$ echo "${0//a/'''}"
    > a'b}c"d
    -b'''}"
    a'bshcd
    [vagrant@localhost ~]$ echo "${0//a/'''}"
    > w'x}y"z
    -b'''}"
    w'xshyz
    [vagrant@localhost ~]$ echo "${0//a/'\'\\"a test'\'}"
    > ^C
    [vagrant@localhost ~]$ echo "${0//a/'\''\\"a test'\'}"
    -b'\''\"a test'\'sh
    [vagrant@localhost ~]$ echo "${0//a/'\''\\"a test'\$0'}"
    > ^C
    [vagrant@localhost ~]$ echo "${0//a/\\"a test'\$0'}"
    > w}x"y
    -b\"a test'$0'}"
    wshxy
    [vagrant@localhost ~]$ echo "${0//a/\\\"a test'\$0'}"
    -b\"a test'$0'sh
    [vagrant@localhost ~]$ echo "${0//a/\\\"a test'\\'$0'}"
    > ^C
    [vagrant@localhost ~]$ echo "${0//a/\\\"a test'\\$0'}"
    -b\"a test'\-bash'sh
    [vagrant@localhost ~]$ 
    
    • 1
  3. DocSalvager
    2020-07-21T00:58:47+08:002020-07-21T00:58:47+08:00

    通过实验,我发现以下语法可用于在 GNU bash 版本 5.0.11(1)-release (x86_64-pc-linux-gnu) 中将单引号转换为双引号...

    text="aaa'bbb'ccc"; echo "${text//$"'"/$'"'}"
    

    结果是...

    aaa"bbb"ccc
    

    请注意,单引号模式必须用双引号括起来,而双引号替换必须用单引号括起来。

    有一个相关的商店记录为...

    extquote  
        If set, $'string' and $"string" quoting is performed within
        ${parameter} expansions  enclosed  in  double quotes.  This option
        is enabled by default.
    
    • 0

相关问题

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

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

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

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

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

Sidebar

Stats

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

    JSON数组使用jq来bash变量

    • 4 个回答
  • Marko Smith

    日期可以为 GMT 时区格式化当前时间吗?[复制]

    • 2 个回答
  • Marko Smith

    bash + 通过 bash 脚本从文件中读取变量和值

    • 4 个回答
  • Marko Smith

    如何复制目录并在同一命令中重命名它?

    • 4 个回答
  • Marko Smith

    ssh 连接。X11 连接因身份验证错误而被拒绝

    • 3 个回答
  • Marko Smith

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

    • 7 个回答
  • Marko Smith

    systemctl 命令在 RHEL 6 中不起作用

    • 3 个回答
  • Marko Smith

    rsync 端口 22 和 873 使用

    • 2 个回答
  • Marko Smith

    以 100% 的利用率捕捉 /dev/loop -- 没有可用空间

    • 1 个回答
  • Marko Smith

    jq 打印子对象中所有的键和值

    • 2 个回答
  • Martin Hope
    EHerman JSON数组使用jq来bash变量 2017-12-31 14:50:58 +0800 CST
  • Martin Hope
    Christos Baziotis 在一个巨大的(70GB)、一行、文本文件中替换字符串 2017-12-30 06:58:33 +0800 CST
  • Martin Hope
    Drux 日期可以为 GMT 时区格式化当前时间吗?[复制] 2017-12-26 11:35:07 +0800 CST
  • Martin Hope
    AllisonC 如何复制目录并在同一命令中重命名它? 2017-12-22 05:28:06 +0800 CST
  • Martin Hope
    Steve “root”用户的文件权限如何工作? 2017-12-22 02:46:01 +0800 CST
  • Martin Hope
    Bagas Sanjaya 为什么 Linux 使用 LF 作为换行符? 2017-12-20 05:48:21 +0800 CST
  • Martin Hope
    Cbhihe 将默认编辑器更改为 vim for _ sudo systemctl edit [unit-file] _ 2017-12-03 10:11:38 +0800 CST
  • Martin Hope
    showkey 如何下载软件包而不是使用 apt-get 命令安装它? 2017-12-03 02:15:02 +0800 CST
  • Martin Hope
    youxiao 为什么目录 /home、/usr、/var 等都具有相同的 inode 编号 (2)? 2017-12-02 05:33:41 +0800 CST
  • Martin Hope
    user223600 gpg —list-keys 命令在将私钥导入全新安装后输出 uid [未知] 2017-11-26 18:26:02 +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