一 IFS
① IFS变量的定义
man -Len -Pcol\ -b bash | sed -ne '/^ *IFS /{N;N;p;q}'
1)字符串'扩展'之后,用来'做单词分割'
2)内建的'read'命令,利用'IFS-->换行符'将文件'每行'内容作为一个'大单词'
② 字符分割中使用IFS
1)Shell把变量'IFS内'的'每一个字符'都当做是'一个分割符'(delimeter),用这些字符作为'每一个字段(word)'的结束符来进行分割
2)如果IFS'没有设置(unset)'或者IFS的值被设置为" \t\n"默认值(space, tab和 newline),那么操作对象的'开始'和'结束处'的所有space, tab和newline序列都'将被忽略',但是操作对象'中间'的space, tab和newline序列会'作为界定符'工作
3)如果IFS值'不是默认值'(程序中对IFS'重新'设置过),只有'出现在IFS内的空白字符'(可能是space, tab或newline中的一个或几个)才会在单词'开始和结束'处被忽略,这里'说的是单词',而'不是整个'操作对象
4)IFS内的'非空白字符'多个'连续出现'时,'每个'非空白字符会被当做'单独的分隔符'看待
5)如果IFS为空("null"),则'不会进行'单词分割
1)解读一
IFS中的'空格'、','、'.'字符都被当作'单词'分割符
备注: 如果以默认的'IFS'分割,',.'也会被当作单词的'一部份'
2)解读二
说明:1个空格、2个空格、3个空格、'1个制表符'、5个空格、6个空格
3)解读三
1)vim中'默认'的'tab'是8个'空格',但是区别于8个空格,表示'一个字符'
+++++++++++'设置Tab键缩进为4个字符'+++++++++++
vim ~/vimrc
set tabstop=4
思考: vimrc中配置是否影响'IFS'的判断?
备注: 这里'测试时'暂时不重新配置'tabstop'
4)解读四
1)用'新的IFS-->B'来分割字符串"aBcBBdBBBeBBBB",显然前面"a"、"b"、"c"、"d"都被分割为'单独'的字符串了
2)从'输出'可见,中间还有'若干个空字符串-->null'
3)这个'空串'就是'IFS'之间分割得到的
4)即使'多个(非空白)分隔符'挨在一起,仍然是'按照单个分隔符'进行分割
'非'空白字符做'IFS'时,如果'不连续'则正常作为'界定符';如果连续,则连续的'非IFS'都由'空格'替代
换句话说: n个'(n>=2)'的'非IFS'字符会由'n'个'空格'代替
注意: 区分多个连续的'IFS空白字符'和'IFS非空白字符的区别'
说明: 从'输出'的情况来看,按照'B',分割除了'14'个所谓的'单词' -->测试:'number计数'
5)解读五
IFS='','不会'做任何分割,所以'作为一个整体'输出
效果等价: "${var}"
③ 特殊参数使用IFS
++++++++++'IFS对'变量$*的'扩展'的影响++++++++++:
1)当用双引号("double quotes")来'引用特殊变量'$*时,会使用'IFS变量的第"1个"字符'来连接$*参数的每一个部分,即"$*"相当于"$1c$2c...",其中c是IFS变量的'第一个'字符
2)如果'没有设置'IFS,则c为空格字符(space),实际上默认情况下IFS变量的'第1个字符就是空格字符'
3)如果'IFS为空'(null),则"$*"内各参数会'直接连接'在一起
1)$*带不带双引号的区别
2)$@带不带双引号的区别
'上面例子'说明: 不管'带不带'双引号,'IFS'无法影响'$@'
注意: 如果脚本'传参'过程,'参数中有空格',要用'引号(单双皆可)括起来'声明是一个整体;如果参数中'有变量',必须加'双引号'
++++++++'$@带双引号与不带双引号区别'++++++++
脚本传参: 变量'本身带有'空格
小结: "$@" 永远是分割成 "$1"、"$2"、"$3"独立的部分
不管变量值是否有'空格',只要是参数带有"",都会作为'一个'完整的'位置参数'
++++++++++'继续探讨一个细节'++++++++++
变量'不加双引号'呢?
是把'$hello'作为一个参数;还是$hello'拆解后'才作为参数
④ 数组引用中使用IFS
关键点: ${name[*]}被'包含在双引号'内,则其将会用'IFS的第1个字符连接'数组的各个元素进行扩展,跟上面使用'双引号引用特殊参数$*'一样
说明: 关'于数组的使用'会开一个'专题'
⑤ 思考1
已知: 我们知道,通常'位置参数'以'空白字符'作为分割符进行分割
思考: 我们是否在'参数传递'时候,修改'位置参数分隔符',使用'其它符'号进行分割,例如':,甚至字母'
说明: 这里尝试用','作为分割符
备注: 该'分割符号'最好不要有'特殊'的含义,被'shell'转义了
+++++++++++++'结论'+++++++++++++
1. IFS 除了对"参数扩展"有作用-->具体'就是'加"双引号"的"$*"
备注: $* 是 $1 - $n, '不包括 $0'
2. IFS 还对'参数位置'有作用,参数位置由'IFS'、及有无" "(作为整体) 决定
备注: 默认'IFS就是空白字符',非特殊情况'不建议'修改
⑥ 思考2
已知: 我们知道'子shell'是可以'继承父shell'的环境变量的
问题: 我们在父shell命令行'非export'修改'IFS'值,子shell继承的是修改'前'的还是修改'后'的
后续测试: 脚本中'调用子脚本'
结论: '父shell'修改IFS,不会影响'子shell';如果想修改'IFS',只能在'子shell'中修改,'无法'通过继承的方式
+++++++++++'其它变量呢'+++++++++++
⑦ read命令
⑧ IFS修改和恢复
场景: 我们只想'临时修改',让其在'特定的时刻'工作
+++++++++++'三种方式'+++++++++++
方式1: 使用一个'中间变量'保存原始值,然后'修改IFS',操作'完成后'再使用中间变量'恢复'IFS
方式2: 使用'local(函数中)来声明'要使用的IFS变量来'覆盖'全局变量,由于local变量只在'局部有效',所以操作完'不需要恢复'IFS
备注: 建议使用$'string'的方式进行'还原'-->'成功'使用反斜杠转义 -->IFS=$' \t\n'
补充: 之'前'的方式是IFS_BAK="$IFS"
⑨ 小结
二 参考博客