Ligne la plus longue d'un fichier

198

Je cherche un moyen simple de trouver la longueur de la plus longue ligne d'un fichier. Idéalement, ce serait une simple commande shell bash au lieu d'un script.

Andrew Prock
la source

Réponses:

270

Utilisation de wc (GNU coreutils) 7.4:

wc -L filename

donne:

101 filename
Daniel
la source
56
Notez que seules les -c -l -m -woptions sont POSIX. -Lest un GNUisme.
Jens
4
Notez également que le résultat de -Ldépend des paramètres régionaux. Certains caractères (à la fois dans l'octet et dans le sens multi-octets) peuvent même ne pas être comptés du tout!
Walter Tross
7
OS X:wc: illegal option -- L usage: wc [-clmw] [file ...]
Hugo
12
OS X: en utilisant homebrew, utilisez gwc pour GNU Word Count gwc -L filename
kaycoder
3
@xaxxon gwcest dans la coreutilsformule, qui installe tous les coreutils GNU avec un gpréfixe.
gsnedders
100
awk '{print length, $0}' Input_file |sort -nr|head -1

Pour référence : recherche de la ligne la plus longue dans un fichier

Point bleu pâle
la source
12
Pourquoi la commande extra cat? Donnez simplement le nom du fichier directement comme argument à awk.
Thomas Padron-McCarthy
18
@Thomas. L'exprimer sous forme de canal est plus général que de spécifier un fichier en option. Dans mon cas, je vais utiliser la sortie canalisée à partir d'une requête de base de données.
Andrew Prock
1
celui-ci est la meilleure réponse car il est plus POSIX (enfin, fonctionne sur OS X)
MK.
5
@MK. Cependant, cette approche est O (n * log (n)) dans le nombre de lignes, tandis que l'approche de Ramon est O (n).
jub0bs
2
Le tri d'un fichier volumineux peut prendre des heures pour se terminer et consommer des gigaoctets, voire des téraoctets d'espace temporaire en fonction de la taille du fichier d'entrée. Pensez à stocker la plus longue longueur et son enregistrement associé, puis à l'imprimer à partir d'un END{}bloc.
Luv2code
67
awk '{ if (length($0) > max) {max = length($0); maxline = $0} } END { print maxline }'  YOURFILE 
Ramon
la source
3
awk '{ if (length($0) > max) max = length($0) } END { print max }' YOURFILE
ke20
5
awk 'length>max{max=length}END{print max}' file
Chris Seymour
8
Cette réponse donne le texte de la ligne la plus longue du fichier plutôt que sa longueur. Je le laisse tel quel, même si la question demande la longueur, car je pense que ce sera utile pour les personnes qui viennent sur cette page en regardant simplement le titre.
Ramon
3
Facile à obtenir le décompte en utilisant WC ..awk '{ if (length($0) > max) {max = length($0); maxline = $0} } END { print maxline }' YOURFILE | wc -c
Nick
1
Pourriez-vous expliquer comment cela fonctionne?
Lnux
23

Juste pour le plaisir et l'éducation, la solution shell POSIX pure , sans utilisation inutile de chat et sans bifurquer vers des commandes externes. Prend le nom de fichier comme premier argument:

#!/bin/sh

MAX=0 IFS=
while read -r line; do
  if [ ${#line} -gt $MAX ]; then MAX=${#line}; fi
done < "$1"
printf "$MAX\n"
Jens
la source
6
ne pas pouvoir lire à partir de std in (via cat) réduit en fait l'utilité de cela, ne l'améliore pas.
Andrew Prock
4
Eh bien, l'OP a dit explicitement "fichier" et sans < "$1"cela, il peut facilement lire depuis stdin. Avec un test, $#il pourrait même faire les deux, selon le nombre d'arguments. Il n'y a tout simplement pas besoin de chats inutiles dans ce monde. Les débutants devraient être enseignés en conséquence dès le début.
Jens
7
Cela devrait être mieux noté, c'est ce que l'utilisateur a demandé. Ajouter la fonction la plus longue () {MAX = 0 IFS = pendant la lecture de la ligne -r; faire si [$ {# line} -gt $ MAX]; alors MAX = $ {# line}; fi fait echo $ MAX} sur votre .bashrc et vous pouvez exécuterlongest < /usr/share/dict/words
skierpage
13
wc -L < filename

donne

101
Anonyme
la source
1
Merci, je cherchais un moyen d'empêcher la wcsortie du nom de fichier :)
Peter.O
11
perl -ne 'print length()."  line $.  $_"' myfile | sort -nr | head -n 1

Imprime la longueur, le numéro de ligne et le contenu de la ligne la plus longue

perl -ne 'print length()."  line $.  $_"' myfile | sort -n

Imprime une liste triée de toutes les lignes, avec les numéros de ligne et les longueurs

.est l'opérateur de concaténation - il est utilisé ici après la longueur ()
$.est le numéro de ligne actuel
$_est la ligne actuelle

Chris Koknat
la source
Nécessite le tri d'un fichier. Les performances seraient terribles même pour les fichiers de taille moyenne et ne fonctionneraient pas pour les fichiers plus volumineux. wc -Lest la meilleure solution que j'ai vue jusqu'à présent.
Tagar
En utilisant un fichier texte de 550 000 000 lignes comme source (British National Corpus), la solution Perl a pris 12 secondes et wc -L3 secondes
Chris Koknat
wc -Lil suffit de compter les enregistrements de nombre - ce Q était sur le point de trouver la ligne la plus longue - pas tout à fait la même, donc ce n'est pas une comparaison précise.
Tagar
6

Point important négligé dans les exemples ci-dessus.

Les 2 exemples suivants comptent les onglets développés

  wc -L  <"${SourceFile}" 
# or
  expand --tabs=8 "${SourceFile}" | awk '{ if (length($0) > max) {max = length($0)} } END { print max }'

Les 2 onglets suivants ne sont pas étendus.

  expand --tabs=1 "${SourceFile}" | wc -L 
# or
  awk '{ if (length($0) > max) {max = length($0)} } END { print max }' "${SourceFile}"

alors

              Expanded    nonexpanded
$'nn\tnn'       10            5
John Kearney
la source
5

On dirait que toute la réponse ne donne pas le numéro de ligne de la plus longue ligne. La commande suivante peut donner le numéro de ligne et la longueur approximative:

$ cat -n test.txt | awk '{print "longest_line_number: " $1 " length_with_line_number: " length}' | sort -k4 -nr | head -3
longest_line_number: 3 length_with_line_number: 13
longest_line_number: 4 length_with_line_number: 12
longest_line_number: 2 length_with_line_number: 11
wangf
la source
Et voilà. Cela trouve mes commentaires odieusement longs. Merci mec.
Philip
Vous pourriez aller plus loin et éliminer le chat. awk '{print length}' test.txt | sort -rn | head -1. Si vous avez également besoin du contenu de la ligne, alors awk '{print length,$0}' test.txt | sort -k1 -rn| head -1
kakoma
3

En perl:

perl -ne 'print ($l = $_) if (length > length($l));' filename | tail -1

cela imprime seulement la ligne, pas sa longueur aussi.

rsp
la source
3

Voici les références de la réponse

cat filename | awk '{print length, $0}'|sort -nr|head -1

http://wtanaka.com/node/7719

Nadir SOUALEM
la source
1
Ce deuxième script awk ne vous indiquera que la longueur la plus longue, pas la ligne la plus longue.
rsp
1
Allez .. Ce sont les mêmes que les deux premières réponses ajoutées avec les références.
Pale Blue Dot
@rsp: je tue la deuxième réponse
Nadir SOUALEM
2

Juste pour le plaisir, voici la version Powershell:

cat filename.txt | sort length | select -last 1

Et pour obtenir juste la longueur:

(cat filename.txt | sort length | select -last 1).Length
eddiegroves
la source
4
Donc, même les programmeurs PowerShell doivent utiliser des chats inutiles?
Jens
1
@Jens Je ne suis pas sûr de bien vous comprendre, cat in Powershell n'est qu'un alias pour Get-Content, dont le comportement dépend du contexte et du fournisseur.
eddiegroves
Peut sortprendre filename.txt comme argument? Ensuite, le chat est inutile car sort length filename.txt | select -last 1évite un tuyau et un processus qui ne fait que copier les données.
Jens
En tant que sidenote, qu'est-ce que PowerShell exactement? Je pensais que l'utilitaire PowerShell était utilisé pour les machines Windows?
franklin
4
@Jens, les données proviennent souvent d'un flux au lieu d'un nom de fichier. Il s'agit d'un idiome d'outils Unix standard.
Andrew Prock
2

Je suis dans un environnement Unix et je travaille avec des fichiers compressés de quelques Go. J'ai testé les commandes suivantes en utilisant un fichier compressé de 2 Go avec une longueur d'enregistrement de 2052.

  1. zcat <gzipped file> | wc -L

et

  1. zcat <gzipped file> | awk '{print length}' | sort -u

Les temps étaient en moyenne

  1. 117 secondes

  2. 109 secondes

Voici mon script après environ 10 runs.

START=$(date +%s) ## time of start

zcat $1 |  wc -L

END=$(date +%s) ## time of end
DIFF=$(( $END - $START ))
echo "It took $DIFF seconds"

START=$(date +%s) ## time of start

zcat $1 |  awk '{print length}' | sort -u

END=$(date +%s) ## time of end
DIFF=$(( $END - $START ))
echo "It took $DIFF seconds"
Jon
la source
Je ne suis pas sûr que ce soit une comparaison valide, je serais inquiet que la awkversion bénéficie de la mise en cache de bloc de disque de la wcversion qui s'exécute en premier (et amorce le cache de disque). Vous devez randomiser l'ordre des personnes appelées en premier au cours des dix manches pour que cet argument reste fidèle.
Canonical Chris
1

Variation sur le thème.

Celui-ci montrera toutes les lignes ayant la longueur de la plus longue ligne trouvée dans le fichier, en conservant l'ordre dans lequel elles apparaissent dans la source.

FILE=myfile grep `tr -c "\n" "." < $FILE | sort | tail -1` $FILE

Alors monfichier

x
mn
xyz
123
abc

va donner

xyz
123
abc
Martin Clayton
la source
0

Si vous utilisez MacOS et obtenez cette erreur: wc: illegal option -- L vous n'avez pas besoin d'installer GNU sipmly.

Si tout ce que vous voulez faire, c'est simplement obtenir le nombre de caractères dans la plus longue ligne du fichier et vous utilisez OS X run:

awk '{print length}' "$file_name" | sort -rn | head -1

Quelque chose comme ça;

echo "The longest line in the file $file_name has $(awk '{print length}' "$file_name" | sort -rn | head -1) characters"

Les sorties:

The longest line in the file my_file has 117 characters

Ivansito87
la source