我们知道,在 Shell 中,一个变量在被展开后,如果它没有被双引号包围起来,那么它展开后的值还会进行一次分词(word splitting,或者叫拆词,分词这个术语已经被搜索引擎相关技术占用了)操作,分成几个词,传给命令的就是几个单独的参数。

举个例子,比如:

$ foo="1 2 3"

$ how_many_args() { echo $#; }

$ how_many_args $foo

3

$ how_many_args "$foo"

1

但是当这个变量出现在 here string 中时,这个分词操作该不该进行?毕竟 here string 的目的是把这个字符串作为整体传给当前命令的标准输入,在这里分词是没有意义的。Bash 文档中也说到:

3.6.7 Here Strings

A variant of here documents, the format is:

<<< word

The word undergoes brace expansion, tilde expansion, parameter and variable expansion, command substitution, arithmetic expansion, and quote removal. Pathname expansion and word splitting are not performed. The result is supplied as a single string to the command on its standard input.

然后 Bash 的实际实现却不是这样的:

$ foo="1|2|3"

$ IFS='|'

$ cat <<< "$foo"

1|2|3

$ cat <<< $foo

1 2 3

这条命令在其他两个支持 here string 的大众 shell ksh 和 zsh 输出的都是 foo 的原值 1|2|3,唯独 Bash 对它进行了分词,然后又用空格 join 成了字符串,所以成了1 2 3。

这个 bug 在 Bash 首次实现 here string 13 年之后直到昨天才被人发现,Bash 作者表示下个版本会修复。我在想为什么这个 bug 这么久才被发现的同时(也许大部分人都习惯在使用变量的时候包上双引号了),又在想为什么 Bash 的文档是对的,实现确是错的,这说明作者是按照某个规范实现的,文档是抄来的,所以没错。然后我查了下 Posix 规范的 Redirection 部分,发现规范里只有 here document,没有 here string。那可能是我猜错了,我又推测:这个语法是 Bash 发明的,只是作者没写测试代码,实现的时候出错了。

网上资料很少,我使劲谷歌了下,发现一本 93 年出版的书 Learning the Korn Shell 详细记载了 hree string 这个特性的来龙去脉

This notation first originated in the Unix version of the rc shell, where it is called a "here string." It was later picked up by the Z shell, zsh (see Appendix A), from which the Korn shell borrowed it. This notation is simple, easy to use, efficient, and visually distinguishable from regular here-documents.

原来是 rc shell(1989)年首次发明了 here document 的变种 here string,后来 zsh (1990)学了过来,然后 ksh(1993)也借了过来,最终 Bash 在 2002 年才抄了过来。 有一点想说的是,我本以为 zsh 这种被人称为终极 shell 的 shell 怎么都是 21 世纪的产物吧,原来 90 年就有了,学习了。

Here String 中不该进行分词的更多相关文章

  1. solr服务中集成IKAnalyzer中文分词器、集成dataimportHandler插件

    昨天已经在Tomcat容器中成功的部署了solr全文检索引擎系统的服务:今天来分享一下solr服务在海量数据的网站中是如何实现数据的检索. 在solr服务中集成IKAnalyzer中文分词器的步骤: ...

  2. Java的String中的subString()方法

    方法如下: public String substring(int beginIndex, int endIndex) 第一个int为开始的索引,对应String数字中的开始位置, 第二个是截止的索引 ...

  3. C++string中有关字符串内容修改和替换的函数浅析

    1.assign() 原型: //string (1) basic_string& assign (const basic_string& str); //substring (2) ...

  4. 从源代码的角度聊聊java中StringBuffer、StringBuilder、String中的字符串拼接

    长久以来,我们被教导字符串的连接最好用StringBuffer.StringBuilder,但是我们却不知道这两者之间的区别.跟字符串相关的一些方法中总是有CharSequence.StringBuf ...

  5. Java-J2SE学习笔记-查找一个String中,subString的出现次数

    1.查找一个String中,subString的出现次数 2.代码 package Test; public class TestStringContain { public static void ...

  6. string中常用的函数

    string中常用的函数 发现在string在处理这符串是很好用,就找了一篇文章放在这里了.. 用 string来代替char * 数组,使用sort排序算法来排序,用unique 函数来去重1.De ...

  7. String 中的秘密

    Navigation:  数据类型相关 > Delphi 的字符及字符串 > [3] - String 中的秘密   //String 的指针地址及实际的内存地址 var str: str ...

  8. String中的==与Empty

    1.String中的==与Equals方法执行结果一样吗? 我们都知道对于引用类型"=="比较的是引用而不是具体的值,但c#中有一种神奇的叫做操作符重载的东西.官方对String类 ...

  9. Java 字符串比较,String 中的一些方法 == 和 equals 的详解

    "==" 是比较的是两个对象的内存地址,而equals方法默认情况下是比较两个对象的内存地址. 1.String str = "hello"  生成的字符串,首 ...

随机推荐

  1. 烂泥:openvpn tun模式下客户端与内网机器通信

    本文由秀依林枫提供友情赞助,首发于烂泥行天下 前两篇文章我们介绍了有关openvpn的搭建与配置文件的讲解,这篇文章我们再聊介绍下,在tun模式下openvpn客户端如何与内网机器通信的问题. 一.实 ...

  2. git 设置代理服务器

    git可以通过以下命令设置代理服务器 git config --global http.proxy http://proxyuser:proxypwd@proxy.server.com:proxypo ...

  3. Android USB Gadget复合设备驱动(打印机)测试方法

    启动Android打印机设备,并用USB线连接电脑主机及Android打印机. Android打印机系统启动完成后,在Windows设备管理器中,可以看到Android Phone设备和USB打印支持 ...

  4. UNIX系统基本结构

    UNIX系统的基本结构如图所示.整个UNIX系统可分为五层:最底层是裸机,即硬件部分:第二层是UNIX的核心,它直接建立在裸机的上面,实现了操作系统重要的功能,如进程管理.存储管理.设备管理.文件管理 ...

  5. java 一些图片

  6. HAOI2015 泛做

    T1 有一棵点数为N的树,树边有边权.给你一个在0~N之内的正整数K,你要在这棵树中选择K个点,将其染成黑色,并将其他的N-K个点染成白色.将所有点染色后,你会获得黑点两两之间的距离加上白点两两之间的 ...

  7. VS 常用高效 快捷键

    强迫智能感知:Ctrl+J.智能感知是Visual Studio最大的亮点之一,选择Visual Studio恐怕不会没有这个原因. 2 撤销:Ctrl+Z.除非你是天才,那么这个快捷键也是最常用的. ...

  8. HTML5入门(CSS样式-------------------(CSS基础知识点----------------------------))

    CSS继承性+层叠性+盒子+浮动 一.CSS继承性 eg:                 <style>                               div{       ...

  9. javascript正则表达式:匹配所有html标签

    此正则表达式收集于网络,但那个网站连复制一下都需要注册会员,鄙视之,所以不提他了.而且,原作者也不可能是那个网站. html标签有<h1></h1>这种成对的,也有<br ...

  10. 电改:OPower资料调研

    0.简介     power公司是于 2007 年创办,是全球领先的家庭能源管理企业.家庭能源数据分析公司.Opower 与公用电力公司合作,抢占家庭消费者"入口",获取家庭消费者 ...