Answers:
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!
unset IFS
随后执行此操作,以使其他命令不会在同一shell中受到影响。
$
意思IFS=$'\n'
?
$
使换行符在字符串内起作用。这也应该local IFS=$'\n'
在函数内部完成。
for
默认情况下,循环在任何空格(空格,制表符,换行符)上分割;一次在一行上工作的最简单方法是改为使用while read
循环,该循环在换行符上分割:
while read i; do echo "$i"; done < ./file_wget_med
我希望您的命令每行吐出一个单词(这就是我用自己的文件测试出来的结果)。如果发生其他事情,我不确定是什么原因引起的。
for i in `ls`; do echo $1; done
通过将输出传递给while命令:,这也是一个很好的选择ls|while read i; do echo $i; done
。这适用于带空格的文件/文件夹名称,而无需更改环境变量。很好的答案。
ls
所以不被认为可以安全地与|
(管道操作员)一起使用。find
除了为此目的更安全之外,它还更加灵活。
pbpaste | while read t; do echo "<string>$t</string>"; done
ls -1
可以用于|
保证每行单格式输出
#!/bin/bash
files=`find <subdir> -name '*'`
while read -r fname; do
echo $fname
done <<< "$files"
经过验证的工作方式,而不是您可能想要的那种班轮,但不可能做到如此优雅。
我会这样写:
cat ./file_wget_med | while read -r j
do
echo $j
done
因为它需要对原始脚本进行最少的更改(使用解决方案除外IFS
,但它bash
不仅修改此循环控制语句的行为)。
cat
这里是不必要的。while
循环接受重定向就好了,这就是为什么这通常写为while IFS= read -r line; do...done < input.txt
Mapfile是一种将行从文件读入索引数组的便捷方法,它不像读取那样可移植,但速度稍快。通过使用for循环,可以避免创建子外壳。
#!/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).
Dandalf非常接近一种功能解决方案,但是永远不要试图将未知输入量(即find ~/.gdfuse -name '*'
)的结果分配给变量!或者,至少试图通过数组变量来做这样的事情;如果您坚持要这么懒!因此,这是Dandalf的解决方案,无需进行危险的操作;一站式
while read -r fname; do
echo $fname;
done <<< `find ~/.gdfuse -name '*'