什么是分词?为什么它在Shell编程中很重要?


16

我对单词拆分在其中扮演的角色感到困惑zsh。在使用C,Python或MATLAB进行编程时,我没有接触过这个概念,这引起了我的兴趣,为什么单词拆分似乎是Shell编程特有的。

之前,我已经在此站点和其他站点上阅读过分词的知识,但没有找到关于此概念的明确解释。维基百科对分词有一个定义,但似乎没有关于如何将其应用于Unix shell的参考。

这是我对以下方面感到困惑的示例zsh

Z Shell FAQ中,我阅读以下内容:

3.1:为什么在$var哪里var="foo bar"没有我所期望的?

在大多数Bourne-shell派生词中,诸如多词变量var="foo bar" 在传递给命令或在for foo in $var循环中使用时都会分解为多个词 。默认情况下,zsh没有这种行为:该变量保持不变。(这不是错误!请参阅下文。)SH_WORD_SPLIT存在此选项是为了提供兼容性。

但是,在《 Z Shell手册》中,我读到以下内容:

SH_WORD_SPLIT (-y) <K> <S>

导致对未引用参数扩展执行字段拆分。请注意,此选项 与分词无关。(请参阅参数扩展。)

为什么会说SH_WORD_SPLIT没有做与分词?单词拆分难道不是一本正经吗?

Answers:


21

早期的shell只有一种数据类型:字符串。但是,通常是在将多个文件名作为参数传递给程序时操纵字符串列表。拆分的另一个常见用例是命令输出结果列表:命令的输出是字符串,但是所需的数据是字符串列表。要将文件名列表存储在变量中,请在文件名之间放置空格。然后像这样的shell脚本

files="foo bar qux"
myprogram $files

所谓myprogram三个参数,作为外壳分割字符串$files成单词。当时,文件名中的空格被禁止或被广泛认为是“未完成”。

Korn shell中引入了阵列:你可以字符串列表存储在一个变量。Korn外壳程序与当时建立的Bourne外壳程序保持兼容,因此裸变量扩展一直在进行字分割,并且使用数组需要一些语法开销。您将在上面编写代码段

files=(foo bar qux)
myprogram "${files[@]}"

Zsh从一开始就有数组,它的作者选择了一种较精巧的语言设计,但以向后兼容为代价。在zsh中(根据默认扩展规则)$var不执行分词;如果要在变量中存储单词列表,则应使用数组;如果您真的想要分词,可以编写$=var

files=(foo bar qux)
myprogram $files

如今,文件名中的空格是您需要解决的,这是因为许多用户希望它们起作用,并且因为许多脚本是在安全敏感的上下文中执行的,攻击者可能会控制文件名。因此,自动分词通常很麻烦。因此,我的一般建议是始终使用双引号,即write "$foo",除非您了解为什么在特定用例中需要分词。(请注意,裸变量展开也将发生遍历。)


谢谢吉尔,这真的很有帮助!说粗略的单词拆分将表格的字符串转换为表格的"word1 word2 word3"列表/数组是否正确"word1" "word2" "word3"?我还用zsh中的特定混淆源更新了OP。
阿梅利奥·瓦兹奎兹·雷纳

1
@intrpc“单词拆分”不是针对自然语言单词而是针对$IFS字符。因此,“字段拆分”是一个更好的名称。但是在外壳文献中,“分词”通常用于此概念。zsh文档令人困惑。
吉尔斯(Gilles)“所以,别再邪恶了”,

1
另请参见rc(plan9 shell,也已移植到Unix),以获得比zsh更好的变量和数组设计。
斯特凡Chazelas

3

分词并不是真正针对外壳的。

第一步,大多数需要解析文本输入的程序都使用某种形式的单词拆分。在从这些“单词”,数字,运算符,字符串,标记以及它们需要处理的任何类似实体中进行识别之前,先完成此操作。

这些shell的特定之处在于它们必须正确地构建称为(C argc / argv,python sys.argv)的命令的参数列表,包括传递带有嵌入式空格的参数,空参数,自定义定界符等。许多shell使用IFS变量在此处提供一定的灵活性。


3

在Zsh的这种特定情况下,单词拆分的定义与字段拆分略有不同。

考虑一下prog a b c,无论您如何设置,它都会传入三个参数IFS。这是分

如果这样做A="a b c"; prog $A,则如果IFS包含空格,则将传入三个参数,否则将传入一个参数。这是字段拆分。

这里的定义很微妙。Zsh文档试图说的是,即使禁用该选项,prog a b c仍然会得到单独的参数(这是人们一直期望的)。


1
zsh的长期开发者Bart Schaefer 确认这确实是该文本的预期含义
斯特凡Chazelas
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.