现在的位置: 首页 > 综合 > 正文

Shell中IFS的妙用

2017年11月24日 ⁄ 综合 ⁄ 共 5110字 ⁄ 字号 评论关闭

在bash中IFS是内部的域分隔符,manual中对其的叙述如下:

IFS The Internal Field Separator that is used for word splitting after expansion and to split lines into words with the read builtin command. The default value is “”.

如下是一些值得注意的地方。
1. IFS的默认值为:空白(包括:空格,tab, 和新行),将其ASSII码用十六进制打印出来就是:20 09 0a (见下面的shell脚本)。

2. IFS对空格的空白的处理和其他字符不一样,左右两半的纯空白会被忽略,多个连续的空白被当成一个IFS处理。

3. S*中使用IFS中的第一个字符。

4. awk中的FS(域分隔符)也和IFS有类似的用法和作用。


我写了一个shell脚本来演示IFS的用法和作用,如下:

View
Code
 BASH

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#! /bin/bash
#author: Jay Ren
#date: 2011.12.10
 
echo "----------------------------------IFS test--------------------------------"
echo "default \$IFS is:(ASSII in hexadecimal value)"
echo -n "$IFS" | xxd -g 1 | awk -F":" '{print $2}' | awk -F" " '{print $1, $2, $3}'
echo "by default, IFS should be a SPACE, a HORIZONTAL TAB, or a LINC FEED."
 
function output_args_one_per_line()
{
arg_list=$*
echo "\$*='$*'"
for arg in $arg_list
do
echo "[$arg]"
done
}
 
echo "--------------------------------------------------------------------------"
echo "set IFS=' ' #dealing with SPACE in IFS is different with other chars."
echo "var=' a b c '"
IFS=' '
var=" a b c "
output_args_one_per_line $var
 
echo "--------------------------------------------------------------------------"
echo "set IFS=':'"
echo "var='::a:b::c:::'"
IFS=':'
var="::a:b::c:::"
output_args_one_per_line $var
 
echo "--------------------------------------------------------------------------"
echo "set IFS='+:-;' #but \$* just use 1st char in IFS as the separator."
echo "var='::a:b::c:::'"
IFS='+:-;'
var="::a:b::c:::"
output_args_one_per_line $var
 
echo "--------------------------------------------------------------------------"
echo "set IFS='-+:;' #but \$* just use 1st char in IFS as the separator."
echo "var='::a:b::c:::'"
IFS='-+:;'
var="::a:b::c:::"
output_args_one_per_line $var
 
echo "--------------------------The END of IFS test-----------------------------"

运行这个脚本结果如下:

View
Code
 BASH

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
master@jay-linux:~/workspace/mygit/shell/sh2011$ ./IFS-test.sh
----------------------------------IFS test--------------------------------
default $IFS is:(ASSII in hexadecimal value)
20 09 0a
by default, IFS should be a SPACE, a HORIZONTAL TAB, or a LINC FEED.
--------------------------------------------------------------------------
set IFS=' '   #dealing with SPACE in IFS is different with other chars.
var='  a b  c   '
$*='a b c'
[a]
[b]
[c]
--------------------------------------------------------------------------
set IFS=':'
var='::a:b::c:::'
$*='::a:b::c::'
[]
[]
[a]
[b]
[]
[c]
[]
--------------------------------------------------------------------------
set IFS='+:-;'   #but $* just use 1st char in IFS as the separator.
var='::a:b::c:::'
$*='++a+b++c++'
[]
[]
[a]
[b]
[]
[c]
[]
--------------------------------------------------------------------------
set IFS='-+:;'   #but $* just use 1st char in IFS as the separator.
var='::a:b::c:::'
$*='--a-b--c--'
[]
[]
[a]
[b]
[]
[c]
[]
--------------------------The END of IFS test-----------------------------
标签: 

=====

IFS是internal field separator的缩写,shell的特殊环境变量。ksh根据IFS存储的值,可以是空格、tab、换行符或者其他自定义符号,来解析输入和输出的变量值。

 

如果有一IP地址220.112.253.111, 欲将这个IP地址颠倒顺序,你可以定义IFS为".",然后直接echo这个地址即可得到此IP的4个数值,然后c重新把IFS设为空格,重新组合四个IP地址的数值即可。

[python] view plaincopy
  1. # The following code segment will only work in ksh,   
  2. # and it will fail in bash  
  3. IP=220.112.253.111  
  4. IFS="."  
  5. TMPIP=$(echo $IP)  
  6. IFS=" " # space  
  7. echo $TMPIP | read ip1 ip2 ip3 ip4  
  8. INVERT_IP=$ip4.$ip3.$ip2.$ip1  

 

 

更详细的IFS的介绍参见下文:(原文地址:http://www.livefirelabs.com/unix_tip_trick_shell_script/oct_2003/10132003.htm

 

Another shell variable that you should become comfortable using is the IFS, or internal field separator, variable.  The shell uses the value stored in IFS, which is the space, tab, and newline characters by default, to delimit words for the read and set
commands, when parsing output from command substitution, and when performing variable substitution.

IFS can be redefined to parse one or more lines of data whose fields are not delimited by the default white-space characters.  Consider this sequence of variable assignments and for loops:

$ line=learn:unix:at:livefire:labs
$ for i in $line
> do
> echo $i
> done
learn:unix:at:livefire:labs
$ OIFS=$IFS
$ IFS=:
$ for i in $line
> do
> echo $i
> done
learn
unix
at
livefire
labs
$

The first command assigns the string “learn:unix:at:livefire:labs” to the variable named line.  You can see from the first for loop that the shell treats the entire string as a single field.  This is because the string does not contain a space, tab, or newline
character. 

After redefining IFS, the second for loop treats the string as four separated fields, each delimited by a colon.  Using a colon for IFS would be appropriate when parsing the fields in a record from /etc/passwd, the user account information file:

livefire:x:100:1::/export/home/livefire:/bin/ksh

Notice that the original value of IFS was stored in OIFS (“O” for original) prior to changing its value.  After you are finished using the new definition, it would be wise to return it to its original value to avoid unexpected side effects that may surface
later on in your script. 

TIP – The current value of IFS may be viewed using the following pipeline:

$ echo "$IFS" | od -b
0000000 040 011 012 012
0000004
$

The output of the echo command is piped into the octal dump command, giving you its octal equivalent.  You can then use an ASCII table to determine what characters are stored in the variable.  Hint: Ignore the first set of zeros and the second newline character
(012), which was generated by echo.

FROM :http://blog.csdn.net/bonny95/article/details/5742075

抱歉!评论已关闭.