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

for j in `cat ./file_wget_med`

do
echo $j

done


运行后结果:

Found.


这是我的数据:

$ cat file_wget_med
2013-09-11 14:27:03 ERROR 404: Not Found.


评论

相关:stackoverflow.com/questions/9084257/…

#1 楼

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!
 


评论


并且要注意IFS上的单引号,因为IFS = $“ \ n”也会拆分“ nn”字符串。我发现设置IFS比使用更复杂的语法或函数更可靠。

– m3nda
15年8月25日在4:08

显然,建议以后取消设置IFS,以免其他命令在同一shell中受到影响。

–鲍里斯·达彭(BorisDäppen)
2015年10月8日14:49

$在IFS = $'\ n'中是什么意思?

–人
16 Dec 4'在8:02

$使换行符在字符串内起作用。这也应该在函数内部使用本地IFS = $'\ n'完成。

–安迪·雷(Andy Ray)
17年3月3日在18:34

@Renn是$'...',称为“ ANSI-C引用”

–αғsнιη
18年6月7日在16:43

#2 楼

默认情况下,for循环在任何空格(空格,制表符,换行符)上拆分;一次在一行上工作的最简单方法是改用while read循环,该循环在换行符之间分割:

while read i; do echo "$i"; done < ./file_wget_med


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

评论


这对于`ls`中的i也是一个很好的选择。回显$ 1;通过将输出传递给while命令来完成:ls | while读取i;回显$ i;完成。这适用于带空格的文件/文件夹名称,而无需更改环境变量。很好的答案。

–吉士
2015年6月1日在21:23



虽然while不能很好地处理第一行和最后一行,但不如IFS的for循环好

–grantbow
15年7月28日在15:16

@jishi因为它主要是为显示而设计的,并且对终端窗口的大小等有所响应,所以ls不适合与|一起使用。 (管道操作员)。除了为此目的更安全之外,find更加灵活。

–很少需要“莫妮卡在哪里”
2015年11月20日在21:48



这是一个很好的答案,我用它将我在Mac OSX上开发的IOS应用的列表转换成PLIST条目。我通过使用pbpaste-> pbpaste |通过clipboad替换了文件输入。读t时做回声“ $ t ”;完成

–大富翁
16 Mar 8 '16在15:43



ls -1可以与|一起使用保证每行一个无格式输出

– AndreyS Scherbakov
16年5月7日,0:08

#3 楼

#!/bin/bash
files=`find <subdir> -name '*'`
while read -r fname; do
    echo $fname
done <<< "$files"


经过验证的工作原理,而不是您可能想要的一种衬管,但无法做到如此优雅。

评论


一个这里串!在所有其他解决方案中最优雅

–伊莱兰·马尔卡(Eliran Malka)
17年1月25日在22:20

请注意,它适用于bash,但不适用于dash等其他外壳。

–desgua
20-05-31在13:35

#4 楼

由于副作用范围小,我喜欢Mitchell Currie的回答的一个扩展,它避免了必须设置变量的情况。

#!/bin/bash
while read -r fname; do
    echo $fname
done <<< "`find <subdir>`"


评论


您可以删除-name'*',它是一样的,不是吗?

– wjandrea
18-12-29在20:24



#5 楼

我会这样写:

cat ./file_wget_med | while read -r j
do
    echo $j
done


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

评论


这里不需要管子和猫。 while循环可以很好地接受重定向,这就是为什么通常将其编写为IFS = read -r行;做...完成
– Sergiy Kolodyazhnyy
18/12/31在5:14

#6 楼

Mapfile是一种将行从文件读入索引数组的便捷方法,它不像读取那样可移植,但速度稍快。通过使用for循环,可以避免创建子shell。

#!/bin/bash

mapfile -t < file.txt

for line in "${MAPFILE[@]}"; do
    echo $line
done


使用管道时请记住,它将while循环放在子shell中。 while循环内的变量之类的更改不会传播到脚本的外部。

示例:

#!/bin/bash

a=0
printf %s\n {0..5} | while read; do
  ((a++))
done
echo $a # 'a' will always be 0.


(更好的解决方案):

#!/bin/bash

b=0
while read; do
  ((b++))
done < <(printf %s\n {0..5})

echo $b # 'b' equal to 6 (works as expected).


#7 楼

Dandalf真正接近一种功能解决方案,但永远不要试图将未知数量的输入结果(即find ~/.gdfuse -name '*')分配给变量!或者,至少试图通过数组变量来做这样的事情;如果您坚持要这么懒!因此,这是Dandalf的解决方案,无需进行危险的操作;并合而为一

while read -r fname; do
  echo $fname;
done <<< `find ~/.gdfuse -name '*'


评论


嘿@odoncaoa,我试图在没有双引号的情况下执行find命令,但它会使所有结果显示为一行。我对该命令的“未知输入量”以及所涉及的危险感到困惑。您能否提供一个危险示例,以及在理论上如何发生这些危险?我真的不希望对此感到懒惰,我只是对其他编程语言更满意。

–丹道夫
19年1月3日,17:38