Bagaimana cara mendapatkan baris terpanjang dari suatu file?

10

Saya tertarik untuk mengetahui nomor baris dari baris terpanjang dari sebuah file.

Misalnya, jika saya memiliki file dengan konten berikut:

lalala
tatatata
abracadabra
mu mu mu

bagaimana saya bisa menulis skrip bash yang akan memberi saya output seperti ini 3 -> abracadabra:?

pengguna214965
sumber

Jawaban:

9

Anda tidak perlu skrip untuk melakukan ini. Perintah sederhana sudah cukup:

egrep -n "^.{$(wc -L < filename)}$" filename

Ini akan berfungsi bahkan ketika Anda memiliki dua atau lebih garis dengan panjang maksimum yang sama.

Jika Anda ingin agar hasilnya persis di formulir ini:, 3 -> abracadabrakemudian gunakan:

egrep -n "^.{$(wc -L < filename)}$" filename | sed 's/:/ -> /'

Referensi:

Radu Rădeanu
sumber
3
@ don.joey: itulah kekuatan unix. Perintah sederhana, yang bisa bekerja bersama. di sini, ia mencari "^. {n} $", yaitu setiap baris yang, antara awal baris ( ^) dan ujungnya ( $) memiliki tepat n karakter ( .{n}). Maka dia hanya perlu menemukan n: untuk ini dia menggunakan GNU-isme, "wc -L filename" (perhatikan bahwa ini bukan posix) yang mengembalikan panjang baris nama file terpanjang. Jadi dia menangkap garis yang memiliki panjang terpanjang. $(cmd)diganti dengan output dari cmd.
Olivier Dulac
1
@OlivierDulac Komentar luar biasa.
Radu Rădeanu
Lebih baik lagi, Anda juga dapat menambahkan (misalnya) -C 3ke opsi grep untuk mendapatkan beberapa baris sebelum dan sesudah untuk konteks
ShadSterling
8

Anda dapat menggunakan awkuntuk mencetak panjang setiap baris ( length()) dan nomor baris ( NR), lalu membalikkan ( -r) sorthasilnya dengan nomor ( -n):

$ awk '{ print length(), NR, $0 | "sort -rn" }' tmp.txt
10 3 abracadabr
8 4 mu mu mu
7 2 tatatat
6 1 lalala

Untuk hanya menampilkan baris pertama:

$ awk '{ print length(), NR, $0 | "sort -rn" }' tmp.txt | head -n 1
10 3 abracadabr
Attila O.
sumber
@ user214965 silakan lihat pembaruan saya, nomor baris yang ditampilkan adalah nomor kedua dalam hasil.
Attila O.
Bagaimana jika ada 2 baris dengan panjang maksimum yang sama?
Radu Rădeanu
@ RaduRădeanu poin bagus. +1 untuk wc -L, saya tidak tahu tentang argumen itu. Ini memang sangat berguna.
Attila O.
4

AO (N) dapat dicapai dengan perl satu liner:

perl -e 'while (<>) { if (length > length $max) { $max=$_}}; print $max'

penggunaan (di mana machin adalah nama file)

cat machin | perl -e 'while (<>) { if (length > length $max) { $max=$_}}; print $max'

atau

perl -e 'while (<>) { if (length > length $max) { $max=$_}}; print $max' machin

atau (kurang jelas tapi lebih pendek)

perl -ne 'if(length>length$m){$m=$_};END{print$m}' machin
MUY Belgia
sumber
Jauh lebih efisien. Terima kasih! Sedang mencarinya.
test30
1
Bekerja dengan file besar +1
h3xStream
0

O (n) Untuk mesin, misalnya OpenWRT, di mana perl tidak tersedia, @ awk @ versi mungkin berguna.

awk 'length > l {l=length;line=$0} END {print line}' FILE

atau python:

python -c "print max(open('$file', 'r'), key=len)"
test30
sumber
0

Jawaban Radu sangat memadai dan disukai, meskipun jika Anda menginginkan solusi yang lebih eksplisit dan berbasis shell, maka Anda dapat menggunakan skrip berikut:

#!/bin/bash
longest_length=0
longest_string=0
while IFS= read -r line || [ -n "${line}"]
do
    if [ "${#line}" -gt "${longest_length}" ]
    then
        longest_length="${#line}"
        longest_string="$line"
    fi
done < "$1"

echo "${longest_string}"

Pemakaian: ./find_longest.sh input.txt

Contoh:

$ cat input.txt                                                          
1 2 
2 3 a a a a
4 5 6 
1 1 1 5

$ ./find_longest.sh input.txt                                            
2 3 a a a a
Sergiy Kolodyazhnyy
sumber