ファイルから最も長い行を読み取るには、while読み取りループを使用しますか?

ファイルから最も長い行を読み取るには、while読み取りループを使用しますか?

私はインターネット検索を試しましたが、whileループを使用して行を読み取るスクリプトが見つかりませんでした。詰まってどこから始めるべきかわかりません。

問題は次のとおりです。標準入力からテキスト行を読み取るためにwhile読み取りループを使用するbashスクリプトLongline.shを作成します。スクリプトはこれまでに読み取った最も長い行を追跡し、入力の終わりに達するとその行を印刷する必要があります。

また、質問にテキスト行を含むファイルを入力するように求められた場合は、そのファイルを読み取るか、テキスト行自体を入力するかはわかりません。

ありがとう、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

1行に1つずつ、すべての行番号のリストを取得できます。最初のものは長さでソートされ、2番目は最大から始まり、行番号でソートされます。

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

方法はとても簡単です。 ewline文字以外のtrすべての入力バイトを1に変換し、入力のすべての行の前に各行の番号を追加し、入力にaを追加し、逆の順序で2cdから始めます。フィールドがソートされます。 aで区切られた行の終わりまで。したがって、最も長い文字列が一番上に浮かび上がります。\ngrep -n: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"

関連情報