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.
#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时做回声“
–大富翁
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
评论
相关:stackoverflow.com/questions/9084257/…