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

相关推荐
promise5249 天前
Linux下载压缩包:tar.gz、zip、tar.bz2格式全攻略
linux·运维·服务器·后端·bash·shell
CILMY2314 天前
【Linux】Shell 与权限:Linux 系统的双重保障
linux·服务器·shell·权限·用户
一鸣@惊人14 天前
Shell脚本快速入门(Linux篇)
linux·运维·服务器·shell
abandondyy17 天前
shell脚本前置基础
linux·shell
向北晴天21 天前
完美解决Jenkins重启后自动杀掉衍生进程(子进程)问题
运维·servlet·jenkins·springboot·shell·sshpublisher
修行者xxl22 天前
标准UEFI Shell命令
shell·uefi
C_eeking23 天前
shell程序设计入门(二)
linux·开发语言·shell
stubborn vegeta25 天前
一款人性化的终端用户界面工具
linux·ui·shell·terminal
对许25 天前
Shell输出、重定向与管道符
linux·shell
青花锁25 天前
阿里云CentOs ClickHouse安装
linux·clickhouse·阿里云·centos·shell·linux脚本