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 / 问题 / 766256
Accepted
john smith
john smith
Asked: 2024-01-06 09:25:40 +0800 CST2024-01-06 09:25:40 +0800 CST 2024-01-06 09:25:40 +0800 CST

测试单词扩展和路径名扩展的简单脚本

  • 772

我正在尝试验证我在这里读到的以下内容:

重要的是要记住,shell 执行我们按顺序描述的所有类型的扩展。这意味着单词扩展在路径名扩展之前执行。因此,如果您循环遍历扩展路径的结果,则不会对这些结果执行分词。

我编写了一个非常简单的脚本,用于验证上面关于单词和路径名扩展的操作顺序的引用:

$ cat test.sh
for path in /home/john/Downloads/*.xlsx

do
    echo "${path}"
done

结果

$ ./test.sh
/home/john/Downloads/CCIE-Collaboration-v3-Learning-Matrix.xlsx
/home/john/Downloads/x y.xlsx

据我所知,单词扩展发生在路径扩展之前,他们使用了一个与此非常相似的脚本来演示它。但我实在不明白这个例子是如何演示的?据我所知,“path”是一个变量,在该变量标识路径之后,该变量将是$path。那么地球上哪里会有单词扩展呢,因为我看不到任何可以考虑扩展的单词。

为了澄清,如果我们运行第一次迭代,$path 是空的,直到它检查“/home/john/Downloads/*.xlsx”,此时它被定义为“/home/john/Downloads/CCIE-Collaboration” -v3-Learning-Matrix.xlsx”,因为这是第一个条目。此时 $path 已被定义。它没有机会应用单词扩展(例如,他们是否说在实际路径名定义第一个结果之前将单词扩展应用于“null”)?

bash
  • 3 3 个回答
  • 68 Views

3 个回答

  • Voted
  1. muru
    2024-01-06T10:05:59+08:002024-01-06T10:05:59+08:00

    我相信他们试图解释的是,在 shell 扩展/home/john/Downloads/*.xlsx为/home/john/Downloads/CCIE-Collaboration-v3-Learning-Matrix.xlsxand /home/john/Downloads/x y.xlsx(“路径名扩展”)之后,它并没有尝试再次将其拆分为/home/john/Downloads/CCIE-Collaboration-v3-Learning-Matrix.xlsx, /home/john/Downloads/xand y.xlsx(“单词拆分”-而不是“单词扩展”)。所有这些都是在for循环开始为变量赋值之前进行的。因此,如果要对路径名扩展的结果执行分词,则循环仅迭代两个值,而不是我们会看到的三个值。这些都与循环体内发生的事情无关。

    另一方面,如果有for i in $(echo a b c),那么 shell 会对命令替换的结果进行分词,并且您会看到三个循环迭代,而不是从 得到的循环迭代for i in "$(echo a b c)"。

    • 2
  2. Best Answer
    terdon
    2024-01-06T19:42:47+08:002024-01-06T19:42:47+08:00

    当作者编写单词扩展时,他们在页面上的其他任何地方都没有使用这个术语(但我被告知确实完全正确,请参阅此处的POSIX 规范),他们似乎指的是拆分操作,他们称之为“分词”。这是 shell 将根据变量值$IFS(通常设置为空格、制表符和换行符)进行拆分的过程。例如,考虑这个脚本(取自这里,这是一个很好的参考,我强烈建议您阅读它):

    #!/bin/sh -
    printf "%d args:" "$#"
    [ "$#" -eq 0 ] || printf " <%s>" "$@"
    echo
    

    该脚本将简单地打印出其参数,显示它们是如何拆分为单词的。尝试使用不同的输入运行:

    $ foo.sh apple orange "passion fruit"
    3 args: <apple> <orange> <passion fruit>
    

    在这里,字符串apple orange "passion fruit"被分成三个“单词” apple,orange和passion fruit。这就是分词。请注意如何防止引号passion fruit被拆分。

    现在,正如文章所述,顺序很重要。如果你阅读bash 手册的“扩展”部分,你会发现:

    展开的顺序是:大括号展开;波形符扩展、参数和变量扩展、算术扩展和命令替换(以从左到右的方式完成);分词;和文件名扩展。

    这里相关的一点是,我上面展示的分词发生在文件名(路径)扩展之前。你的误解在这里:

    为了澄清,如果我们运行第一次迭代,$path 是空的,直到它检查“/home/john/Downloads/*.xlsx”,此时它被定义为“/home/john/Downloads/CCIE-Collaboration” -v3-Learning-Matrix.xlsx”,因为这是第一个条目。此时 $path 已被定义。

    不,$path此时已定义,它不会扩展到/home/john/Downloads/CCIE-Collaboration-v3-Learning-Matrix.xlsx循环内部,而是在循环开始之前。我们可以使用与您所拥有的稍有不同的脚本来分解这两者,即分词和路径名扩展:

    #!/bin/bash
    
    words="x y.xlsx *.xlsx"
    for word in $words; do
      echo "word is '$word'"
    done
    

    在包含以下内容的目录中尝试该脚本:

    $ ls -1
    CCIE-Collaboration-v3-Learning-Matrix.xlsx
    'x y.xlsx'
    

    输出是:

    $ foo.sh
    word is 'x'
    word is 'y.xlsx'
    word is 'CCIE-Collaboration-v3-Learning-Matrix.xlsx'
    word is 'x y.xlsx'
    

    那么发生了什么?

    1. 该变量根据 的值$words拆分为$IFS单词。结果是 3 个单词:z、y.xlsx和*.xlsx。

    2. 接下来,这三个单词中的每一个都进行路径扩展。这使得x和y.xlsx保持不变,因为它们不能扩展到路径,而是*.xlsx变成x y.xlsx和CCIE-Collaboration-v3-Learning-Matrix.xlsx。

    作者试图表达的观点是,由于在 shell 扩展*.xlsx为 x y.xlsx和时已经发生了分词CCIE-Collaboration-v3-Learning-Matrix.xlsx,因此不会发生进一步的分词,并且x y.xlsx尽管包含空格,但仍被视为单个单词。


    请注意,这个答案的第一个版本是错误的,因为我将标记化与分词混淆了。

    • 2
  3. ilkkachu
    2024-01-08T02:40:15+08:002024-01-08T02:40:15+08:00

    句子“这意味着单词扩展在路径名扩展之前执行。” 引用中的内容毫无意义,因为来源从未定义“单词扩展”应该是什么。在下一句话中,他们提到了分词,这在页面前面已经描述过,可能就是他们的意思。所以,忽略“单词扩展”这个短语,在这种情况下它是错误的,简单明了。

    引用的下一句话更有意义:

    因此,如果您循环遍历扩展路径的结果,则不会对这些结果执行分词。

    考虑以下情况,我们创建两个文件oneword并two words在一个空目录中,然后循环./*:

    touch 'oneword' 'two words'
    i=0 
    for f in ./*; do
        printf "%d: %s\n" "$i" "$f"
        i=$(( i+1 ))
    done
    

    输出如下,显示循环迭代了 、 两项./oneword,./two words这两项是路径名扩展的直接结果,而后一个文件名没有进一步拆分。

    0: ./oneword
    1: ./two words
    

    如果在路径名扩展之后发生单词拆分,则第二个文件名将进一步拆分为./two words,并且循环将总共运行三次。(假设默认IFS。)


    上面的 Q 继续

    据我所知,单词扩展发生在路径扩展之前,他们使用了一个与此非常相似的脚本来演示它。

    但正如上面所说,这是没有意义的。您引用的来源没有定义“单词扩展”对他们意味着什么,并且不清楚您对这个短语的含义。这不是你的错:你被一个无法保持其术语一致的来源所困惑。

    现在,从技术上讲,POSIX 规范使用短语“单词扩展”来表示所有波浪号扩展、参数扩展、命令替换、算术扩展、字段拆分(通常称为单词拆分)、路径名/文件名扩展和引号删除。但是您的消息来源使用该短语的上下文与该定义没有意义。单词扩展不能发生在路径扩展“之前”,因为单词扩展包括路径扩展。

    那么地球上哪里会有单词扩展呢,因为我看不到任何可以考虑扩展的单词。

    再次强调,取决于你的意思。POSIX 意义上的“分词”几乎涵盖了所有内容,因此在 Q 中的脚本中,有“单词扩展”(路径名扩展)到/home/john/Downloads/*.xlsx文件名,以及“单词扩展”(参数扩展)到"${path}"当前文件名中。变量的值path。(我上面的脚本也有算术展开的情况。)

    • 1

相关问题

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

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

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

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

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

Sidebar

Stats

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

    模块 i915 可能缺少固件 /lib/firmware/i915/*

    • 3 个回答
  • Marko Smith

    无法获取 jessie backports 存储库

    • 4 个回答
  • Marko Smith

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

    • 4 个回答
  • Marko Smith

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

    • 5 个回答
  • Marko Smith

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

    • 3 个回答
  • 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
    user12345 无法获取 jessie backports 存储库 2019-03-27 04:39:28 +0800 CST
  • Martin Hope
    Carl 为什么大多数 systemd 示例都包含 WantedBy=multi-user.target? 2019-03-15 11:49:25 +0800 CST
  • Martin Hope
    rocky 如何将 GPG 私钥和公钥导出到文件 2018-11-16 05:36:15 +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

热门标签

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