我可以这样迭代文件的行:
while read l; do echo $l; done < file
有没有办法只迭代前 5 行?
答案1
只需执行以下操作:
n=5
while IFS= read -ru3 line && (( n-- )); do
printf 'Got this line: "%s"\n' "$line"
done 3< some-file
不过,在这里,如果涉及文本处理,最好是使用文本处理工具:
LC_ALL=C sed 's/.*/Got this line: "&"/;5q' < some-file
或者:
awk '{print "Got this line: \""$0"\""}; NR == 5 {exit}' < some-file
或者:
perl -lne 'print qq(Got this line: "$_"); last if $. == 5' < some-file
有关的:
答案2
有很多方法可以迭代文件的前五行;这里有一些。请注意,最后一个是最有效的,通常是更好的方法解决此类问题的方法是使用 shell 脚本循环。
蛮力:
{
OIFS="$IFS" IFS=
read -r line && printf "%s\n" "$line"
read -r line && printf "%s\n" "$line"
read -r line && printf "%s\n" "$line"
read -r line && printf "%s\n" "$line"
read -r line && printf "%s\n" "$line"
IFS="$OIFS"
} <file
一个循环:
for ((i=1; i<=5; i++))
do
IFS= read -r line
printf "%s\n" "$line"
done <file
另一个循环,适用于小范围,因为表达式在求值之前会扩展为所有值的列表(即{1..5}
转换为1 2 3 4 5
前执行):
for i in {1..5}
do
IFS= read -r line
printf "%s\n" "$line"
done <file
仅考虑文件的开头,但要注意在此循环中设置的任何变量将无法访问在它之外
head -n5 file |
while IFS= read -r line
do
printf "%s\n" "$line"
done
根本不使用循环
head -n5 file
sed 5q file
答案3
您可以使用流程替代,从 的输出重定向,head -n 5 file
而不仅仅是file
.与使用来自 的管道不同head -n 5 file
,通过进程替换,while 循环在当前 shell 中运行,并且能够在该 shell 中设置/更改变量,并以其他方式影响其环境 - 子进程或子 shell(例如管道)无法影响它的父母的环境。
例如:
while read l; do printf '%s\n' "$l"; done < <(head -n 5 file)
我会解释为什么我使用printf
而不是echo
以及关于不使用 shell 处理文本的警告,但是史蒂芬的回答已经这样做了。我建议您阅读该答案中的链接。