bash是由内置变量IFS
作为字段分隔符,IFS变量的值直接影响脚本如何解析参数,其默认值为\<space\>\<tab\>\<newline\>
, 即空格、制表符以及换行符。
遇到一个需求是需要设置分隔符为换行符\n
, 即一行一个字段,空格和制表符不会分割字段。很容易想到的办法是重设IFS变量值:
OLD_IFS=$IFS
IFS='\n'
# do some work here
IFS=$OLD_IFS
但结果并非所期望的,bash会把IFS
的单独的每个字符当作了分隔符,即分隔符被设置成下划线\
和字母n
,而不是\n
。
通过google搜索,得知需要把\n转化成ANSI-C Quoting, 解决办法是把字符串放入$’string’中,即设置为:
IFS=$'\n'
顺便搜了下$
字符在shell字符串的用途,在what-does-it-mean-to-have-a-dollarsign-prefixed-string-in-a-script中详细介绍了字符串前面加$
字符的两种形式,一种是使用单引号,另一种是使用双引号,这二者的区别为:
There are two different things going on here, both documented in the bash manual
$’
Dollar-sign single quote is a special form of quoting: ANSI C Quoting Words of the form $’string’ are treated specially. The word expands to string, with backslash-escaped characters replaced as specified by the ANSI C standard.
$”
Dollar-sign double-quote is for localization: Locale translation A double-quoted string preceded by a dollar sign (‘$’) will cause the string to be translated according to the current locale. If the current locale is C or POSIX, the dollar sign is ignored. If the string is translated and replaced, the replacement is double-quoted.
因此单引号表示转化成ANSI-C字符,双引号则表示将字符串本地化。
以下是一个实例,ping /etc/hosts的主机名为video-开头的主机名,检查网络状况!
#!/bin/bash
trap "echo 'interrupted!';exit 1" SIGHUP SIGINT SIGTERM
OLD_IFS=$IFS
IFS=$'\n'
for i in `awk '$0!~/^$/ && $0!~/^#/ && $2~/^video/ {print $1,$2}' /etc/hosts`
do
ADDR=$(echo $i | cut -d' ' -f 1)
DOMAIN=$(echo $i | cut -d' ' -f 2)
if ping -c 2 $ADDR &>/dev/null
then
echo $DOMAIN ok!
else
echo $DOMAIN off-line!
fi
done
IFS=$OLD_IFS