如何使用 bash 迭代文件中的前 5 行?

如何使用 bash 迭代文件中的前 5 行?

我可以这样迭代文件的行:

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 处理文本的警告,但是史蒂芬的回答已经这样做了。我建议您阅读该答案中的链接。

相关内容