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

相关推荐
Selina K7 小时前
shell脚本知识点记录
笔记·shell
Dangks3 天前
[运维] 服务器本地网络可用性检查脚本
linux·运维·服务器·shell·network·系统工具
DreamADream4 天前
Shell编程中关于用户操作报错`用户无法登录`
shell
江上清风山间明月8 天前
shell脚本编写注意细节 ==、=等的区别
bash·shell·注意·相等·细节·==·=
188_djh12 天前
# linux从入门到精通-从基础学起,逐步提升,探索linux奥秘(十六)--shell
linux·运维·bash·shell·shell入门·shell变量·linux入门到精通
RamboPan12 天前
Mac 使用脚本批量导入 Apple 歌曲
macos·自动化·shell·apple·script
I'm Jie13 天前
一站式学习 Shell 脚本语法与编程技巧,踏出自动化的第一步
linux·ssh·shell·shell脚本·shell编程
rainsc16 天前
当多核变单核:破解CPU核心神秘失踪的终极指南!
服务器·shell
一丝晨光16 天前
编程语言支持中文变量吗?三字符组是什么来源?为什么结构体要考虑对齐?如何确定语言使用的地址是不是物理地址?用户态应用程序如何获取变量的物理地址?
java·linux·c++·c·shell·结构体·虚拟地址
188_djh16 天前
# linux从入门到精通-从基础学起,逐步提升,探索linux奥秘(十七)--shell运算符
linux·运维·bash·shell·shell脚本附带参数·shell运算符·shell文件测试运算符