如何在带有空格的“for”循环中读取完整行

use*_*118 166 command-line bash scripts

我正在尝试for为文件运行一个循环,我想显示整行。但它只显示最后一个字。我想要完整的线路。

for j in `cat ./file_wget_med`

do
echo $j

done
Run Code Online (Sandbox Code Playgroud)

运行后结果:

Found.
Run Code Online (Sandbox Code Playgroud)

这是我的数据:

$ cat file_wget_med
2013-09-11 14:27:03 ERROR 404: Not Found.
Run Code Online (Sandbox Code Playgroud)

Rad*_*anu 239

for当循环看到空格、制表符或换行符等任何空白时,它就会拆分。因此,您应该使用IFS(内部字段分隔符)

IFS=$'\n'       # make newlines the only separator
for j in $(cat ./file_wget_med)    
do
    echo "$j"
done
# Note: IFS needs to be reset to default!
Run Code Online (Sandbox Code Playgroud)

  • 显然,建议事后“取消设置 IFS”,以便在同一个 shell 中不影响其他命令。 (31认同)
  • 并注意 IFS 上的单引号,因为 IFS=$"\n" 也会拆分 "nn" 字符串。我发现 set IFS 比使用更复杂的语法或函数更可靠。 (5认同)
  • `IFS=$'\n'` 中的 `$` 是什么意思? (4认同)
  • @Renn 那是 `$'...'` 已知的“[ANSI-C 引用](https://www.gnu.org/software/bash/manual/html_node/ANSI_002dC-Quoting.html)” (3认同)
  • `$` 使换行符在字符串内起作用。这也应该在函数内使用 `local IFS=$'\n'` 来完成。 (2认同)

evi*_*oup 109

for默认情况下,循环在任何空格(空格、制表符、换行符)上拆分;一次处理一行的最简单方法是使用while read循环代替,它在换行符处拆分:

while read i; do echo "$i"; done < ./file_wget_med
Run Code Online (Sandbox Code Playgroud)

希望你的命令每行吐出一个单词(这是我用我自己的文件测试它时发生的情况)。如果发生其他事情,我不确定是什么原因造成的。

  • 这也是 `for i in \`ls\` 的一个很好的替代方案;做回声 $1; done`,通过管道输出到 while 命令:`ls|while read i; 做回声 $i; 完成`。这适用于带空格的文件/文件夹名称,无需更改环境变量。很好的答案。 (15认同)
  • `ls -1` 可以与 `|` 一起使用以保证每行一个无格式输出 (4认同)
  • 这是一个很好的答案,我用它来将我拥有的列表转换为我在 mac OSX 上开发的 IOS 应用程序的 PLIST 条目。我使用 **pbpaste** -&gt; `pbpaste | 通过管道传输剪贴板替换了文件输入。读 t 时;做 echo "&lt;string&gt;$t&lt;/string&gt;"; 完成` (3认同)

小智 21

#!/bin/bash
files=`find <subdir> -name '*'`
while read -r fname; do
    echo $fname
done <<< "$files"
Run Code Online (Sandbox Code Playgroud)

经过验证的工作,不是您可能想要的一种衬里,但不可能优雅地这样做。

  • 这里字符串!最优雅的所有其他解决方案 IMO (2认同)

Dan*_*alf 7

这是 Mitchell Currie 答案的一个轻微扩展,我喜欢它,因为副作用的范围很小,避免了必须设置变量:

#!/bin/bash
while read -r fname; do
    echo $fname
done <<< "`find <subdir>`"
Run Code Online (Sandbox Code Playgroud)


小智 6

我会这样写:

cat ./file_wget_med | while read -r j
do
    echo $j
done
Run Code Online (Sandbox Code Playgroud)

因为它需要对原始脚本进行最少的更改(使用 的解决方案除外IFS,但它bash不仅修改此循环控制语句的行为)。