Shell中的IFS

IFS是shell的内置变量,IFS是一个字符串,里面的每一个字符都用作分隔符进行单词分割。

IFS变量只在当前shell起作用。

一、对$*的影响

先做参数替换把$*替换成参数列表。相当于args[]

然后下面分两种情况:

(1)当$*不在双引号里面时,要做单词分割,把args的每个元素继续按IFS分割成多个单词,比如$1可能分成两个单词,$2可能分成三个单词

(2)当$*在双引号里面时,跳过单词分割,直接把args每个元素以IFS第一个字符连接成单个单词,即"$1c$2c$3"。c是IFS第一个字符

举例:

#!/bin/bash
old_ifs=$IFS
IFS=:
set "a:b-c" "d:e f"
echo 参数个数:$#
echo $*
loopcount=0
for i in $*; do
     echo $i
    ((loopcount++))
done
echo 循环次数:$loopcount



echo "$*"
loopcount=0
for i in "$*"; do
     echo $i
     echo "$i"
    ((loopcount++))
done
echo 循环次数:$loopcount
IFS=$old_ifs



运行结果

参数个数:2
a b-c d e f
a
b-c
d
e f
循环次数:4
a:b-c:d:e f
a b-c d e f
a:b-c:d:e f
循环次数:1

二、对$@的影响

先做参数替换把$@替换成参数列表。相当于args[]

然后下面分两种情况:

(1)当$@不在双引号里面时,要做单词分割,把args的每个元素继续按IFS分割成多个单词,比如$1可能分成两个单词,$2可能分成3个单词

(2)当$@在双引号里面时,跳过单词分割,把每个元素单独作为单词,最后是多个单词,即"$1" "$2" ...

举例:

#!/bin/bash
old_ifs=$IFS
IFS=:
set "a:b-c" "d:e f"
echo 参数个数:$#
echo $@
loopcount=0
for i in $@; do
     echo $i
    ((loopcount++))
done
echo 循环次数:$loopcount



echo "$@"
loopcount=0
for i in "$@"; do
       echo $i
       echo "$i"
    ((loopcount++))
done
echo 循环次数:$loopcount
IFS=$old_ifs



运行结果:

参数个数:2
a b-c d e f
a
b-c
d
e f
循环次数:4
a:b-c d:e f
a b-c
a:b-c
d e f
d:e f
循环次数:2

三、对变量替换结果的影响

先做变量替换,然后再分下面两种情况:

(1)当不在双引号里面时,要做单词分割,把替换后字符串按IFS分割成多个单词。

(2)当在双引号里面时,跳过单词分割,保持原样,是单个单词。

举例:

#!/bin/bash
old_ifs=$IFS
IFS=':;'
var="; a:b;:c:"
echo 不带引号变量:$var
echo -n 不带引号变量逐字符:
echo -n $var |od -a
echo 带引号变量:"$var"
echo -n 带引号变量逐字符:
echo -n "$var" |od -a
echo ----------
loopcount=0
for i in $var; do
       echo $i
    ((loopcount++))
done
echo 循环次数:$loopcount

echo ----------
loopcount=0
for i in $var; do
       echo -n $i |od -a  
       ((loopcount++))
done
echo 循环次数:$loopcount


echo ----------
loopcount=0
for i in "$var"; do
       echo $i
       echo "$i"
       ((loopcount++))
done
echo 循环次数:$loopcount

echo ----------
loopcount=0
for i in "" " a" "b" "" "c"; do  
       echo -n $i |od -a  
       ((loopcount++))
done   
echo 循环次数:$loopcount

IFS=$old_ifs



运行结果

不带引号变量: a b c
不带引号变量逐字符:0000000 sp sp a sp b sp sp c
0000010
带引号变量:; a:b;:c:
带引号变量逐字符:0000000 ; sp a : b ; : c :
0000011
----------

 a
b

c
循环次数:5
----------
0000000
0000000 sp a
0000002
0000000 b
0000001
0000000
0000000 c
0000001
循环次数:5
----------
a b c
; a:b;:c:
循环次数:1
----------
0000000
0000000 sp a
0000002
0000000 b
0000001
0000000
0000000 c
0000001
循环次数:5

可以看到for i in $var与for i in "" " a" "b" "" "c"是一模一样的。

四、对命令替换的影响

有3个文件 a.txt 'b c.js' t.sh

以空格和换行为分隔符

#!/bin/bash
echo `ls`
loopcount=0
for i in `ls`; do
    echo $i
    ((loopcount++))
done
echo 循环次数:$loopcount

echo "`ls`"
loopcount=0
for i in "`ls`"; do
    echo $i
    echo "$i"
    ((loopcount++))
done
echo 循环次数:$loopcount



运行结果:
a.txt b c.js t.sh
a.txt
b
c.js
t.sh
循环次数:4
a.txt
b c.js
t.sh
a.txt b c.js t.sh
a.txt
b c.js
t.sh
循环次数:1

以换行符为分隔符

#!/bin/bash
old_ifs=$IFS
IFS=$'\n'
echo `ls`
loopcount=0
for i in `ls`; do
    echo $i
    ((loopcount++))
done
echo 循环次数:$loopcount

echo "`ls`"
loopcount=0
for i in "`ls`"; do
    echo $i
    echo "$i"
    ((loopcount++))
done
echo 循环次数:$loopcount
IFS=$old_ifs



运行结果:
a.txt b c.js t.sh
a.txt
b c.js
t.sh
循环次数:3
a.txt
b c.js
t.sh
a.txt b c.js t.sh
a.txt
b c.js
t.sh
循环次数:1

以空格为分隔符

#!/bin/bash
old_ifs=$IFS
IFS=' '
echo `ls`
loopcount=0
for i in `ls`; do
    echo $i
    ((loopcount++))
done
echo 循环次数:$loopcount

echo "`ls`"
loopcount=0
for i in "`ls`"; do
    echo $i
    echo "$i"
    ((loopcount++))
done
echo 循环次数:$loopcount
IFS=$old_ifs


运行结果:
a.txt
b c.js
t.sh
a.txt
b
c.js
t.sh
循环次数:2
a.txt
b c.js
t.sh
a.txt
b c.js
t.sh
a.txt
b c.js
t.sh
循环次数:1

总结一下:

双引号中

不在双引号中

$*

替换后不做分割,把各个参数用IFS连起来。

最终是一个单词

"$1c$2c$3..."

c 是IFS首个字符

替换后做分割,对每个参数继续以IFS进行分割

最终是多个单词

word1 word2 word3 word4 word5...

word1 word2可能来自参数$1

word3 word4来自参数$2

word5来自参数$3

$@

替换后不做分割,各个参数单独做单词。

最终是多个单词

"$1" "$2" "$3"...

替换后做分割,对每个参数继续以IFS进行分割

最终是多个单词

word1 word2 word3 word4 word5...

word1 word2可能来自参数$1

word3 word4来自参数$2

word5来自参数$3

变量

var="1-2-3"

IFS='-'

替换后不做分割,保持原样。

最终是一个单词

"1-2-3"

替换后做分割,以IFS进行分割

最终是多个单词

"1" "2" "3"

命令

`ls`

a.txt

b c.js

IFS=' '

替换后不做分割,保持原样。

最终是一个单词

"a.txt\nb c.js"

替换后做分割,以IFS进行分割

最终是多个单词

"a.txt\nb" "c.js"

不加双引号时,$*和$@是一样的。

加双引号时,$*和$@是不一样的,最好使用$@

五、一些应用:

(一)批量重命名文件名含有空格的文件

重命名前:

txt 2014.02.14.log
txt 2014.02.15.log

重命名后:

txt_2014_02_14.log
txt_2014_02_15.log

脚本内容

oldifs=$IFS
IFS=$'\n'
for file in `ls`;do
     mv $file `sed -r 's/[ .]/_/g;s/(.*)_/\1./' <<< $file`
done
IFS=$oldifs

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值