最近在学习《Linux命令行和shell脚本编程大全》(第四版)这本书,对于自己遇到的问题以及通过搜索引擎和书籍中的解决方案进行一个案例的剖析,希望对于像我这样的初学者,有一个帮助。
1 for循环 | 从变量中读取值列表
正常的for循环可以有不用的方式来读取值列表
1.1 从列表中读取值列表
正常来说:
代码语言:shell复制#!/bin/bash
for test in alabama alaska arizona washintoDC
do
echo Now going to $test
done
当列表中的值存在特殊字符,比如说空格,'
等,以上语句就会失效,那么应该用"
或者的方式将特殊字符包裹起来,如下:
#!/bin/bash
for test in alabama alaska arizona washintoDC "New York" "shipping's world"
do
echo Now going to $test
done
1.2 从变量中读取值列表
正常来说:
代码语言:shell复制#!/bin/bash
list="alabama alaska arizona washintoDC"
for test in $list
do
echo Now going to $test
done
如果变量中有元素含有特殊值,比如空格、制表符或者换行符等如何处理。
将数据转换为数组:
代码语言:shell复制#!/bin/bash
list=("alabama" "new york" "arizona" "arkanses")
for test in "${list[@]}"
do
echo Now going to $test
done
1.3 从命令中读取值列表
有一个文件stat.txt
代码语言:shell复制[root@iZuf6gxtsgxni1r88kx9rtZ linux_cmd]# cat stat.txt
Alabama 12
Alasaka 12
Arizona 124
Arkansas 245
Colorado 235
Connecticut 324
Delaware 23
Florida 255
Georgia 234
我们要读取每一行作为一个值应该是:
代码语言:shell复制#!/bin/bash
IFS_SAVE=$IFS
IFS=$'n'
for test in `cat stat.txt`
do
echo "line : $test"
done
IFS=$IFS_SAVE
2 关于字段分隔符的使用
而第1节中的为什么for循环可以读取以空格(或者精确点说:空格,制表符和换行符)来切割变量,就是由于IFS的影响。
2.1 默认情况
在默认情况下,它即是以空格来切割的,而这种切割是忽略字符串或者变量首尾的空格的,只会针对字符串中间的空格,并且对连续的空格仅切割一次,如下:
代码语言:shell复制#!/bin/bash
for test in liaoning jilin heilongjiang shanghai
do
echo "Go to $test"
done
结果
代码语言:shell复制[root@iZuf6gxtsgxni1r88kx9rtZ linux_cmd]# sh for_input_param.sh
Go to liaoning
Go to jilin
Go to heilongjiang
Go to shanghai
2.2 设置多个分隔符
如果指定,可以指定一个分隔符或者多个分隔符,而在具体分割过程中也是可以按照多个分隔符进行分割,如下:
代码语言:shell复制#!/bin/bash
IFS_SAVE=$IFS
IFS=$'n:,'
for test in `cat stat.txt`
do
echo "line: $test"
done
IFS=$IFS_SAVE
stat.txt内容如下:
代码语言:txt复制Ala,bama 12
Alasaka 12
Arkansas 245
Conne:cticut 324
Delaware 23
F,lorida 255
Georgia 234
结果如下:
代码语言:shell复制line: Ala
line: bama 12
line: Alasaka 12
line: Arkansas 245
line: Conne
line: cticut 324
line: Delaware 23
line: F
line: lorida 255
line: Georgia 234
我们可以看到在IFS
中设置的分隔符均起作用了。
2.3 混淆点
针对IFS分隔符的设置可以有多种方式:a、IFS='n';b、IFS="n";c、IFS=$"n";d、IFS=$'n'
我们使用hexdump
命令来看下如此的方式究竟有何不同:
#!/bin/bash
IFS_SAVE=$IFS
IFS='n'
echo "IFS设置为'n',结果如下:"
echo -n "$IFS" | hexdump -C
echo "*****************************"
IFS="n"
echo "IFS设置为"n",结果如下:"
echo -n "$IFS" | hexdump -C
echo "*****************************"
IFS=$"n"
echo "IFS设置为$"n",结果如下:"
echo -n "$IFS" | hexdump -C
IFS=$'n'
echo "IFS设置为$'n',结果如下:"
echo -n "$IFS" | hexdump -C
IFS=$IFS_SAVE
结果如下:
代码语言:shell复制IFS设置为'n',结果如下:
00000000 5c 6e |n|
00000002
*****************************
IFS设置为"n",结果如下:
00000000 5c 6e |n|
00000002
*****************************
IFS设置为$"n",结果如下:
00000000 5c 6e |n|
00000002
IFS设置为$'n',结果如下:
00000000 0a |.|
00000001
我们可以看到,前三种方式的设置,转换为16进制都是两个字符,一个是5c
,一个是n
,也就是设置以后是文本的n,而不是换行符,而第四种设置方式才是真正的换行符,所以,在设置IFS分隔符的时候要注意单引号和双引号的区别。