星期二, 十二月 09, 2008

利用 IFS 变量在 Bash 中进行行处理

有一个文件
$ cat services.txt
锘?name script(basename) args("") mask(1/2) script_type(1/2[d]) dss
#step = "300"
#rra = "RRA:MIN:0.5:1:2016 RRA:MIN:0.5:6:8640 RRA:MIN:0.5:36:2920 RRA:MIN:0.5:288:1825 RRA:AVERAGE:0.5:1:2016 RRA:AVERAGE:0.5:6:8640 RRA:AVERAGE:0.5:36:2920 RRA:AVERAGE:0.5:288:1825 RRA:MAX:0.5:1:2016 RRA:MAX:0.5:6:8640 RRA:MAX:0.5:36:2920 RRA:MAX:0.5:288:1825"

disk adapter "-t alarm /home/testenv/script/check_disk -l -w 10% -c 5% -e" 1 2
inode adapter "-t alarm /home/testenv/script/check_disk -l -W 15% -K 10% -e" 1 2
load adapter "-t alarm /home/testenv/script/check_load -w 4,5,6 -c 6,7,8" 1 2
#load adapter "-t state /home/testenv/script/check_load -w 4,5,6 -c 6,7,8" 2 2
crond adapter "-t alarm /home/testenv/script/check_procs -w 1:1 -c 1:3 -C crond" 1 2
portmap adapter "-t alarm /home/testenv/script/check_procs -w 1:1 -c 1:3 -C portmap" 1 2
syslog adapter "-t alarm /home/testenv/script/check_procs -w 1:1 -c 1:3 -C syslogd" 1 2
snmpd adapter "-t alarm /home/testenv/script/check_procs -w 1:1 -c 1:3 -C snmpd" 1 2
sshd adapter "-t alarm /home/testenv/script/check_procs -w 1:1 -c 1:3 -C sshd" 1 2
#cpu
#mem
#disksp
#diskio
#iftraffic
#ifpackage

现在我需要按行处理,将每一行的结果进行重组并作为参数去调用另一个脚本。所以首先我需要得到每一行的结果,按照以前的做法,我通常是使用 while 循环来做,因为使用 for 得到的结果不对:
$ for line in $(grep -Pv '^$|^#' services.txt);do echo $line;done
锘?name
script(basename)
args("")
mask(1/2)
script_type(1/2[d])
dss
disk
adapter
"-t
alarm
/home/testenv/script/check_disk
-l
-w
10%
-c
5%
-e"
1
2
inode
adapter
"-t
alarm
/home/testenv/script/check_disk
-l
-W
15%
-K
10%
-e"
1
2
load
adapter
"-t
alarm
/home/testenv/script/check_load
-w
4,5,6
-c
6,7,8"
1
2
crond
adapter
"-t
alarm
/home/testenv/script/check_procs
-w
1:1
-c
1:3
-C
crond"
1
2
portmap
adapter
"-t
alarm
/home/testenv/script/check_procs
-w
1:1
-c
1:3
-C
portmap"
1
2
syslog
adapter
"-t
alarm
/home/testenv/script/check_procs
-w
1:1
-c
1:3
-C
syslogd"
1
2
snmpd
adapter
"-t
alarm
/home/testenv/script/check_procs
-w
1:1
-c
1:3
-C
snmpd"
1
2
sshd
adapter
"-t
alarm
/home/testenv/script/check_procs
-w
1:1
-c
1:3
-C
sshd"
1
2

得到的不是每一行的输出!

而使用 while 结果如下:
$ grep -Pv '^$|^#' services.txt | while read line; do echo $line; done
锘? ame script(base ame) args("") mask(1/2) script_type(1/2[d]) dss
disk adapter "-t alarm /home/teste v/script/check_disk -l -w 10% -c 5% -e" 1 2
i ode adapter "-t alarm /home/teste v/script/check_disk -l -W 15% -K 10% -e" 1 2
load adapter "-t alarm /home/teste v/script/check_load -w 4,5,6 -c 6,7,8" 1 2
cro d adapter "-t alarm /home/teste v/script/check_procs -w 1:1 -c 1:3 -C cro d" 1 2
portmap adapter "-t alarm /home/teste v/script/check_procs -w 1:1 -c 1:3 -C portmap" 1 2
syslog adapter "-t alarm /home/teste v/script/check_procs -w 1:1 -c 1:3 -C syslogd" 1 2
s mpd adapter "-t alarm /home/teste v/script/check_procs -w 1:1 -c 1:3 -C s mpd" 1 2
sshd adapter "-t alarm /home/teste v/script/check_procs -w 1:1 -c 1:3 -C sshd" 1 2


但是使用 while 循环会启动一个子 Shell,如果我要在循环后再进行其他操作则会有问题,因为此时 $line 已经不可用了,于是可以用 IFS 来做 for 循环,因为 for 循环不会在子 Shell 中进行:
$ IFS=$'\n' && for line in $(grep -Pv '^$|^#' services.txt);do echo $line;done
锘?name script(basename) args("") mask(1/2) script_type(1/2[d]) dss
disk adapter "-t alarm /home/testenv/script/check_disk -l -w 10% -c 5% -e" 1 2
inode adapter "-t alarm /home/testenv/script/check_disk -l -W 15% -K 10% -e" 1 2
load adapter "-t alarm /home/testenv/script/check_load -w 4,5,6 -c 6,7,8" 1 2
crond adapter "-t alarm /home/testenv/script/check_procs -w 1:1 -c 1:3 -C crond" 1 2
portmap adapter "-t alarm /home/testenv/script/check_procs -w 1:1 -c 1:3 -C portmap" 1 2
syslog adapter "-t alarm /home/testenv/script/check_procs -w 1:1 -c 1:3 -C syslogd" 1 2
snmpd adapter "-t alarm /home/testenv/script/check_procs -w 1:1 -c 1:3 -C snmpd" 1 2
sshd adapter "-t alarm /home/testenv/script/check_procs -w 1:1 -c 1:3 -C sshd" 1 2


注意这个地方必须使用单引号,使用双引号的结果不对:
$ IFS=$"\n" && for line in $(grep -Pv '^$|^#' services.txt);do echo $line;done
锘?
ame script(base
ame) args("") mask(1/2) script_type(1/2[d]) dss
disk adapter "-t alarm /home/teste
v/script/check_disk -l -w 10% -c 5% -e" 1 2
i
ode adapter "-t alarm /home/teste
v/script/check_disk -l -W 15% -K 10% -e" 1 2
load adapter "-t alarm /home/teste
v/script/check_load -w 4,5,6 -c 6,7,8" 1 2
cro
d adapter "-t alarm /home/teste
v/script/check_procs -w 1:1 -c 1:3 -C cro
d" 1 2
portmap adapter "-t alarm /home/teste
v/script/check_procs -w 1:1 -c 1:3 -C portmap" 1 2
syslog adapter "-t alarm /home/teste
v/script/check_procs -w 1:1 -c 1:3 -C syslogd" 1 2
s
mpd adapter "-t alarm /home/teste
v/script/check_procs -w 1:1 -c 1:3 -C s
mpd" 1 2
sshd adapter "-t alarm /home/teste
v/script/check_procs -w 1:1 -c 1:3 -C sshd" 1 2

没有评论: