for循环种读取列表值出现特殊值的处理方式以及关于IFS分隔符的解读

最近在学习《Linux命令行和shell脚本编程大全》(第四版)这本书,对于自己遇到的问题以及通过搜索引擎和书籍中的解决方案进行一个案例的剖析,希望对于像我这样的初学者,有一个帮助。

1 for循环 | 从变量中读取值列表

正常的for循环可以有不用的方式来读取值列表

1.1 从列表中读取值列表

正常来说:

bash 复制代码
 #!/bin/bash
 for test in alabama alaska arizona washintoDC
 do
         echo Now going to $test
 done

当列表中的值存在特殊字符 ,比如说空格,'等,以上语句就会失效,那么应该用"或者``的方式将特殊字符包裹起来,如下:

bash 复制代码
 #!/bin/bash
 for test in alabama alaska arizona washintoDC "New York" "shipping's world"
 do
         echo Now going to $test
 done

1.2 从变量中读取值列表

正常来说:

bash 复制代码
 #!/bin/bash
 list="alabama alaska arizona washintoDC"
 for test in $list
 do
         echo Now going to $test
 done

如果变量中有元素含有特殊值,比如空格、制表符或者换行符等如何处理。

将数据转换为数组:

bash 复制代码
 #!/bin/bash
 list=("alabama" "new york" "arizona" "arkanses")
 for test in "${list[@]}"
 do
     echo Now going to $test
 done

1.3 从命令中读取值列表

有一个文件stat.txt

csharp 复制代码
 [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

我们要读取每一行作为一个值应该是:

bash 复制代码
 #!/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 默认情况

在默认情况下,它即是以空格来切割的,而这种切割是忽略字符串或者变量首尾的空格的,只会针对字符串中间的空格,并且对连续的空格仅切割一次,如下:

bash 复制代码
 #!/bin/bash
 for test in liaoning jilin    heilongjiang     shanghai
 do
         echo "Go to $test"
 done

结果

css 复制代码
 [root@iZuf6gxtsgxni1r88kx9rtZ linux_cmd]# sh for_input_param.sh 
 Go to liaoning
 Go to jilin
 Go to heilongjiang
 Go to shanghai

2.2 设置多个分隔符

如果指定,可以指定一个分隔符或者多个分隔符,而在具体分割过程中也是可以按照多个分隔符进行分割,如下:

bash 复制代码
 #!/bin/bash
 IFS_SAVE=$IFS
 IFS=$'\n:,'
 for test in `cat stat.txt`
 do      
         echo "line: $test"
 done    
 IFS=$IFS_SAVE

stat.txt内容如下:

r 复制代码
 Ala,bama 12
 Alasaka 12
 Arkansas 245
 Conne:cticut 324
 Delaware 23
 F,lorida 255
 Georgia 234

结果如下:

yaml 复制代码
 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命令来看下如此的方式究竟有何不同:

bash 复制代码
 #!/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

结果如下:

markdown 复制代码
 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对应的是\,一个是6e对应的是n,也就是文本\n,而不是真正的换行符,而第四种设置方式才是真正的换行符,所以,在设置IFS分隔符的时候要注意单引号和双引号的区别,不要混淆。

相关推荐
岚天start2 天前
解决方案—K8S集群的日志按天并按照命名空间分类定时同步到日志服务器
服务器·docker·kubernetes·shell·日志备份
aitav03 天前
⚡ Linux awk 命令全面详解(包括记录、字段、命令空间)
linux·运维·服务器·bash·shell·awk
VincentHe7 天前
当 ServerCat 遇上 Shell 环境变量:一次服务器监控性能优化记录与探索
服务器·shell·监控
虚伪的空想家9 天前
ip网段扫描机器shell脚本
android·linux·网络协议·tcp/ip·shell·脚本·network
谅望者10 天前
Linux文件查看命令完全指南:cat、less、head、tail、grep使用详解
linux·excel·less·shell·文件操作·命令行·系统运维
hello_25012 天前
Shell脚本高效编写技巧
运维·shell
leaf9z13 天前
阿里云ECS在线扩容磁盘
阿里云·云计算·shell
gfdgd xi15 天前
deepin 终端,但是版本是 deepin 15 的
linux·python·架构·ssh·bash·shell·deepin
大米粥哥哥18 天前
Qt QProcess基于Linux的命令管道符号无效问题【已解决】
linux·qt·shell·qprocess·1024程序员节·管道符号
缘友一世25 天前
深入理解Shell与反弹Shell:从原理到实战
linux·网络安全·shell