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 / 问题 / 485970
Accepted
De Novo
De Novo
Asked: 2018-12-05 10:52:20 +0800 CST2018-12-05 10:52:20 +0800 CST 2018-12-05 10:52:20 +0800 CST

为什么波浪号前缀在赋值之前会扩展,而大括号却不会

  • 772

tl;目录

在 bash 中,大括号扩展发生在波浪号扩展之前。但是,波浪号前缀似乎在变量赋值之前扩展,而大括号扩展则没有。为什么?

细节和例子

bash 中的大括号扩展被记录为发生在波浪线扩展之前:

大括号扩展在任何其他扩展之前执行

据我了解,波浪号扩展发生在变量赋值之前,如下例所示:

# UNQUOTED TILDE PREFIX, TILDE EXPANSION EXPECTED
tilde=~
echo "$tilde"
# /Users/DeNovo
[[ $tilde == "$HOME" ]] && echo "literal match"
# literal match

# QUOTED TILDE PREFIX, TILDE EXPANSION DOES NOT OCCUR
lit_tilde='~'
echo "$lit_tilde"
# ~
# UNQUOTED TILDE PREFIX PRODUCED AND EVALUATED, TILDE EXPANSION OCCURS
# AS EXPECTED
eval echo "$lit_tilde"
# /Users/DeNovo
[[ $lit_tilde == "~" ]] && echo "literal match"
# literal match

这些例子似乎表明右操作数left=right在被绑定为左操作数的值之前经历波浪号扩展。

然而,大括号扩展不会发生在变量赋值之前,其行为类似于将文字波浪号绑定到变量(相对于扩展的特殊字符/前缀)

# UNQUOTED BRACE, BUT NO EXPANSION. BRACE LITERAL IS PRESERVED
brace={a..c}
echo "$brace"
# {a..c}
[[ $brace = "a b c" ]] || echo "doesn't match"
# doesn't match
[[ $brace = "{a..c}" ]] && echo "literal match"
# literal match

# SIMILAR TO THE LITERAL TILDE, EVALUATING THE VARIABLE VALUE 
# RESULTS IN BRACE EXPANSION
eval echo "$brace"
# a b c

将这两个扩展合并到一个示例中,您可以看到波浪号扩展发生而大括号扩展没有发生:

combined=~/dir_{a..c}
echo "$combined"
# /Users/DeNovo/dir_{a..c}

大括号防止内部代字号在分配期间扩展

internal_tilde={~,~+}/new_dir
echo "$internal_tilde"
# {~,~+}/new_dir

# vs the same output, not in a variable
echo {~,~+}/new_dir
/Users/DeNovo/new_dir /Your/Working/Directory/new_dir

只是为了澄清,我不是在问如何让变量包含大括号扩展的结果,而是为什么尽管发生在波浪线扩展之前,大括号扩展不会在变量赋值之前发生。有几种方法可以获得所需的行为。这是一个:

# PROCESS SUBSTITUTION GIVES THE DESIRED BEHAVIOR
brace_exp="$(echo {a..c})"
echo "$brace_exp"
a b c
[[ $brace_exp = "a b c" ]] && echo "literal match"
# literal match

再说一遍,为什么波浪号扩展发生在变量赋值之前,而大括号扩展(应该发生在波浪号扩展之前)却没有发生在变量赋值之前。大概分配在某种我不知道的方面是特殊的。

bash brace-expansion
  • 2 2 个回答
  • 326 Views

2 个回答

  • Voted
  1. Stephen Kitt
    2018-12-05T11:05:26+08:002018-12-05T11:05:26+08:00

    在您的测试中,{a..c}未展开,因为它是变量赋值的一部分,并单独处理:

    1. 解析器标记为变量赋值(命令名称前面的那些)和重定向的词被保存以供以后处理。
    2. 不是变量赋值或重定向的词被扩展(参见Shell Expansions)。如果扩展后还有任何单词,则将第一个单词作为命令名称,其余单词作为参数。

    分配的值不进行大括号扩展:

    1. 每个变量赋值中' ' 之后的文本在=赋值给变量之前会经历波浪号扩展、参数扩展、命令替换、算术扩展和引号删除。
    • 4
  2. Best Answer
    De Novo
    2018-12-05T15:32:39+08:002018-12-05T15:32:39+08:00

    @StephenKitt 的回答指向相关文档 (+1),表明该行为是预期的(为什么波浪号前缀在赋值之前扩展但大括号不扩展?因为它们就是这样定义的)。

    回复:大括号扩展很特殊的一个可能原因,让我们看看变量赋值时没有发生什么:

    • 大括号扩展
    • 单词拆分(解析器拆分行,但不拆分该单词内的扩展结果)
    • 文件名扩展

    这些正是可以改变扩展字数的操作:

    外壳扩展:

    只有大括号展开、分词、文件名展开可以改变展开的字数

    在示例中,变量是一个字符串而不是一个数组,并且应该只包含一个单词。

    分配数组时确实会发生大括号扩展,如brace=({a..c}). 要使用更复杂的示例:

    internal_tilde=({~,~+}/new_dir)
    echo "${internal_tilde[@]}"
    # /Users/DeNovo/new_dir /Your/Working/Directory/new_dir
    

    所以,我认为这种设计是有道理的(而不是历史上的怪事)。波浪号扩展不会改变字数。大括号扩展确实如此。如果您希望您的变量包含多个单词,请使用专为此设计的数据结构。

    • 0

相关问题

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

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

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

  • `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