使用 while read 循环读取文件中最长的行?

使用 while read 循环读取文件中最长的行?

我一直在谷歌搜索,但找不到任何使用 while 循环来读取行的脚本。我被困住了,不知道从哪里开始

问题如下:编写一个bash脚本longestline.sh,使用 while read 循环从其标准输入读取文本行。脚本应该跟踪迄今为止读取的最长行,当到达输入末尾时,打印该行。

另外,我不确定问题是否要求我输入一个包含文本行的文件,它会读取该文件或自己输入文本行。

谢谢,KB

答案1

根据 cuonglm 的链接,bash应避免循环。

awk本着这种精神,下面的代码使用标准 unix 工具获取文件中最长行的长度,但没有bash循环:

awk '{n=length($0)>n?length($0):n} END{print n}' file

如果您想打印最长的行,而不是获取其长度,请使用:

awk '{longest=length($0)>length(longest)?$0:longest} END{print longest}' 

答案2

我已经很长一段时间没有写过 bash 了,所以我会接受任何类型的批评:)我的解决方案是这样的:

n=0
longest=""
while read line; do
    len=`echo $line | wc -m`
    if [ $len -ge $n ]; then
        n=$len
        longest=$line
    fi
done 

echo $longest

我读了 @cuonglm 的建议,但我想不出一种方法来使用更少的进程调用来做到这一点。当然,我愿意接受建议。

关于你的最后一个问题,这真的不重要。该脚本可以与您输入的行一起工作,或者与用作输入的文件一起工作。

答案3

您可以获得所有行号的列表,每行一个,第一个按长度排序,第二个按行号从最大的开始排序,例如...

</path/to/infile LC_ALL=C \
tr -c \\n 1|grep -n '.\|'|sort -t: -rnk2

该方法非常简单 -tr将每个不是\newline 字符的输入字节转换为 1,在其输入中的所有行grep -n前面添加每行的编号,然后将 a 添加到其输入中,然后按相反的数字顺序从 2cd 字段到行尾进行排序由 a 分隔。所以最长的 1 串会浮到顶部。:sort:

但您应该注意,如果输入包含多字节字符,那么这将仅按字节编号,而不是按字符编号。扎实做好后一件事可不是一件小事(据我了解)

无论如何 - 在 ASCII 语言环境中 - 即使对于非常大的输入,上述内容也应该非常快。它几乎不需要其他任何东西就可以成为一个完整的解决方案:

f=/path/to/file
n=$(<"$f" tr -c \\n 1|grep -n '.\|'|sort -t: -rnk2|head -n1)
l=$(<"$f" head -n"${n%:*}"|tail -n1)
printf "Line #%s at #${#l} bytes. Its contents:\n%s\n" \
   "${n%:*} is (possibly tied-for) the longest in $f" "$l"

相关内容