我一直在谷歌搜索,但找不到任何使用 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
将每个不是\n
ewline 字符的输入字节转换为 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"