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

相关推荐
山鬼谣me12 小时前
macbook pro查询并修改命令提示符的格式
shell·macbook
牛马大师兄1 天前
Shell脚本编程之正则表达式
linux·运维·服务器·开发语言·ssh·bash·shell
LoveLinuxShell2 天前
推荐Linux命令行运维工具: WowKey--实现自动化批量化标准化Linux设备运维
linux·运维·shell·自动化批量化标准化
一名用户4 天前
实用的alias别名命令——比2=1+1简单的基础命令
后端·shell
白嫖一茶4 天前
shell语言替换脚本、填补整个命令行
linux·shell
星如雨落8 天前
Linux Shell 脚本使用YAD工具实现Shell图形化界面
linux·shell
苏琢玉9 天前
MySQL 备份 Shell 脚本:支持远程同步与阿里云 OSS 备份
mysql·shell
一名用户10 天前
看似简单的read命令-->shell中最重要的输入命令!
后端·shell
小小小小小纯洁13 天前
Shell脚本调试模式详解
shell
火车叼位13 天前
OpenWRT服务异常的日志追踪技巧
linux·shell