Here String 中不该进行分词
我们知道,在 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:
<<< wordThe 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 中不该进行分词的更多相关文章
- solr服务中集成IKAnalyzer中文分词器、集成dataimportHandler插件
昨天已经在Tomcat容器中成功的部署了solr全文检索引擎系统的服务:今天来分享一下solr服务在海量数据的网站中是如何实现数据的检索. 在solr服务中集成IKAnalyzer中文分词器的步骤: ...
- Java的String中的subString()方法
方法如下: public String substring(int beginIndex, int endIndex) 第一个int为开始的索引,对应String数字中的开始位置, 第二个是截止的索引 ...
- C++string中有关字符串内容修改和替换的函数浅析
1.assign() 原型: //string (1) basic_string& assign (const basic_string& str); //substring (2) ...
- 从源代码的角度聊聊java中StringBuffer、StringBuilder、String中的字符串拼接
长久以来,我们被教导字符串的连接最好用StringBuffer.StringBuilder,但是我们却不知道这两者之间的区别.跟字符串相关的一些方法中总是有CharSequence.StringBuf ...
- Java-J2SE学习笔记-查找一个String中,subString的出现次数
1.查找一个String中,subString的出现次数 2.代码 package Test; public class TestStringContain { public static void ...
- string中常用的函数
string中常用的函数 发现在string在处理这符串是很好用,就找了一篇文章放在这里了.. 用 string来代替char * 数组,使用sort排序算法来排序,用unique 函数来去重1.De ...
- String 中的秘密
Navigation: 数据类型相关 > Delphi 的字符及字符串 > [3] - String 中的秘密 //String 的指针地址及实际的内存地址 var str: str ...
- String中的==与Empty
1.String中的==与Equals方法执行结果一样吗? 我们都知道对于引用类型"=="比较的是引用而不是具体的值,但c#中有一种神奇的叫做操作符重载的东西.官方对String类 ...
- Java 字符串比较,String 中的一些方法 == 和 equals 的详解
"==" 是比较的是两个对象的内存地址,而equals方法默认情况下是比较两个对象的内存地址. 1.String str = "hello" 生成的字符串,首 ...
随机推荐
- ubuntu下怎么给普通用户赋予sudo权限
ununtu系统安装过程中,系统会提示建立一个默认用户,比如用户名为:zhuhui.这个默认用户具有一定的管理功能,即可以通过sudo命令执行root权限的操作.由于Ubuntu系统默认不允许通过ro ...
- 迅为最新推出iTOP-6818开发平台无缝支持4418开发板
iTOP-6818开发板是一款四核ARM 八核开发板与iTOP-4418开发板完全兼容,CPU主频1.4GHz,内存1GB DDR3(2GB可选),存储16GB EMMC,板载千兆以太网,GPS,WI ...
- WPFTookit Chart 入门
如何使用WPFToolKit Chart private void button1_Click(object sender, EventArgs e) { var s = new Series(); ...
- UNITY 之FixedUpdate
这个机制的加入 比 AS3好了很多 AS3的EnterFrame相当于UNITY的Update 但是FLASH做不了也是因为浏览器的限制吧! Here's how the fixed time ste ...
- angular学习笔记(二十九)-$q服务
angular中的$q是用来处理异步的(主要当然是http交互啦~). $q采用的是promise式的异步编程.什么是promise异步编程呢? 异步编程最重要的核心就是回调,因为有回调函数,所以才构 ...
- HTML5入门(---------------HTML——基本骨架--------------)
HTML基础 一.HTML 超文本标记语言.英文全拼:HyperText Markup Language.负责网页的语义描述. 二.HTML基本骨架 <!DOCTYPE html> < ...
- vc++2013中使用MySQL connector/C++ 1.1.4静态链接报错
包含头文件 #include <mysql_connection.h> #include <mysql_driver.h> #include <cppconn/state ...
- SQLite剖析之锁和并发控制
在SQLite中,锁和并发控制机制都是由pager.c模块负责处理的,用于实现ACID(Atomic.Consistent.Isolated和Durable)特性.在含有数据修改的事务中,该模块将确保 ...
- CSS编写技巧
1.尽量少的使用全局的重置代码 全局重置代码:*{margin:0; padding:0;}对于熟悉CSS的人来说并不陌生,并且有很多人的第一句CSS代码就是这句.它可以避免不同浏览器的默认间距不同而 ...
- C# 6.0 新特性
1.C# 6.0 示例 1: 自动属性支持初始化, 字符串嵌入的新方式, 通过 Using Static 引用静态类, nameof 表达式CSharp6/Demo1.xaml.cs /* * C# ...