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分隔符的时候要注意单引号和双引号的区别,不要混淆。

相关推荐
花落已飘9 小时前
STM32中实现shell控制台(命令解析实现)
stm32·shell
Johny_Zhao20 小时前
Docker 一键安装部署 JumpServer 堡垒机
linux·网络安全·信息安全·云计算·shell·jumpserver·ldap·yum源·系统运维
Johny_Zhao1 天前
Ubuntu系统安装部署Pandawiki智能知识库
linux·mysql·网络安全·信息安全·云计算·shell·yum源·系统运维·itsm·pandawiki
bcbobo21cn2 天前
初步了解Linux etc/profile文件
linux·运维·服务器·shell·profile
1.01^100015 天前
[2-02-02].第59节:功能函数 - 函数基础
shell
___波子 Pro Max.16 天前
Shell脚本中&&和||语法解析
shell
lewis_lk18 天前
文本处理三剑客: grep、sed、awk使用指南
后端·shell
Johny_Zhao19 天前
企业级LDAP-RADIUS深度集成高可用方案
linux·网络·python·网络安全·信息安全·云计算·shell·cisco·系统运维
Johny_Zhao19 天前
基于CentOS Stream 8的物联网平台深度优化方案
linux·网络·网络安全·信息安全·云计算·shell·yum源·系统运维
Johny_Zhao21 天前
CentOS Stream 8 高可用 Kuboard 部署方案
linux·网络·python·网络安全·docker·信息安全·kubernetes·云计算·shell·yum源·系统运维·kuboard