关于IFS与-d参数的疑问:为何不同read用法执行结果有差异?
为什么三段处理PATH的Shell代码表现不同?
第一段可正常运行的代码
while read -r -d: path; do ls $path; done <<< "${PATH}"
这段代码的核心是read -d:参数:-d用来指定输入的分隔符,这里把冒号:设为分隔符。PATH的格式是目录1:目录2:目录3:...,每次read会读取到下一个冒号为止,把这段内容赋值给path;最后即使输入末尾没有冒号,read遇到输入结束时也会把最后一段目录路径读进来,所以能逐个遍历PATH里的所有目录,ls自然能正常执行。
第二段执行失败的代码
while IFS=: read -r path; do ls $path; done <<< "${PATH}"
这里的误区是混淆了IFS和read的分隔逻辑:
IFS=:的作用是在读取一行内容时,把行内的内容按冒号分割成多个变量,但这里只给了一个变量path,所以read会把整行(也就是整个PATH字符串,比如/usr/bin:/bin:/usr/local/bin)完整赋值给path。- 而
read默认是按换行符来分割输入的,这里用<<<传入的PATH是一整行,所以循环只会执行一次,ls会尝试访问一个名为/usr/bin:/bin:/usr/local/bin的路径,显然这个路径不存在,所以脚本失败。
第三段可正常运行的代码
while read -r single; do ls $single; done <<< "${PATH//:/ }"
这段用了Shell的参数替换${PATH//:/ },把PATH里所有的冒号:替换成空格,这样原来的目录1:目录2:目录3就变成了目录1 目录2 目录3。read默认会把空白符(空格、制表符、换行)作为分隔符,每次读取一个目录路径赋值给single,循环逐个处理每个目录,因此ls能正常执行。
内容的提问来源于stack exchange,提问作者Helgi Sidorov
相关产品推荐
相关产品推荐

