Je cherche la méthode la plus simple pour imprimer la plus longue ligne d'un fichier. J'ai fait quelques recherches sur Google et, étonnamment, je n'ai pas semblé trouver de réponse. J'imprime fréquemment la longueur de la plus longue ligne d'un fichier, mais je ne sais pas comment imprimer la plus longue ligne. Quelqu'un peut-il fournir une solution pour imprimer la plus longue ligne d'un fichier? Merci d'avance.
35
Réponses:
UPD : résumant tous les conseils dans les commentaires
la source
cat
) et utiliser un tube sont des opérations coûteuses, sans compter qu’il est plus efficace pour awk de lire le fichier. Les conséquences sur les performances sont clairement perceptibles si cela est fait fréquemment, et même dans ce cas, vous utilisez complètement malcat
.cat
n'est pas inutile ici. Cela pourrait être inutile pour un ordinateur, mais pour un lecteur humain, cela pourrait être très utile. La première variante montre clairement l'entrée. Le flux est plus naturel (de gauche à droite). Dans le second cas, vous ne savez pas quelle est la saisie, sauf si vous faites défiler la fenêtre.cat
.< file command
fonctionne très bien.< filename command
est équivalent àfilename < command
dans chaque coquille que j'ai essayée. Mais une fois que vous en êtes conscient, vous pouvez en tirer parti lorsque vous écrivez de longs tubes qui indiquent clairement la direction du flux de données (sans invoquer de commande supplémentaire):< input-file command1 | command2 | command3 > output-file
la source
Ceci lit d'abord le fichier à l'intérieur de la substitution de commande et affiche la longueur de la plus longue ligne (auparavant,
expand
convertit les tabulations en espaces pour surmonter la sémantique dewc -L
- chaque tabulation de la ligne ajoutera 8 au lieu de 1 à la longueur de la ligne). Cette longueur est ensuite utilisée dans unesed
expression signifiant "trouver une ligne de ce nombre de caractères, l'imprimer, puis quitter". Cela peut donc être aussi optimal que la plus longue ligne se trouve en haut du fichier, heheh (merci pour les commentaires impressionnants et constructifs).Un autre, j'avais pensé plus tôt que le sed (en bash):
la source
-L, --max-line-length
imprime la longueur de la plus longue ligne, conformément à la page de manuel, mais si vous creusez plus profondément (comme lorsque vous obtenez des résultats erronés / inattendus ), vous constaterez que cette option incrémente la longueur de 8 pour chaque 1 caractère tab\x09
voir cette Unix & Linux Q / Ased -rn "/.{$(<file expand -t1 |wc -L)}/p" file
read line
interprétera les caractères échappés barre oblique inverse comme le charbon littéral, par exemple\A
resloves àA
qui des rapports sur les cours effectivement un plus court que octet utilisation réelle ... Pour éviter cela échappé à l' interprétation, l' utilisation:read -r line
. . . . Aussi, pour que la version sed + wc s'arrête après la première "ligne la plus longue", remplacezp
par{p;q}
..sed -rn "/.{$(<file expand -t1 |wc -L)}/{p;q}" file
Voici une solution Perl:
Ou, si vous voulez imprimer toutes les lignes les plus longues
Comme je n'avais rien de mieux à faire, j'ai effectué des tests sur un fichier texte 625M. Étonnamment, ma solution Perl était toujours plus rapide que les autres. Certes, la différence avec la
awk
solution acceptée est minime, mais elle est là. Évidemment, les solutions imprimant plusieurs lignes étant plus lentes, j'ai donc trié par type, du plus rapide au plus lent.N'imprimez qu'une des plus longues lignes:
Imprimer toutes les lignes les plus longues:
la source
Grep la première ligne la plus longue
La commande est inhabituellement difficile à lire sans pratique, car elle mélange la syntaxe shell et regexp.
Pour l'explication, je vais d'abord utiliser le pseudocode simplifié. Les lignes commençant par
##
ne sont pas exécutées dans le shell.Ce code simplifié utilise le nom de fichier F et laisse de côté les citations et des parties de regexps pour des raisons de lisibilité.
Comment ça marche
La commande a deux parties, une
grep
- et unewc
invocation:## grep "^.{$( wc -L F )}$" F
Le
wc
est utilisé dans une extension de processus$( ... )
, il est donc exécuté avantgrep
. Il calcule la longueur de la plus longue ligne. La syntaxe d'expansion du shell est mélangée à la syntaxe du modèle d'expression régulière d'une manière qui prête à confusion, donc je décomposerai l'extension du processus:## wc -L F
42
## grep "^.{42}$" F
Ici, l’extension du processus a été remplacée par la valeur qu’elle renverrait, créant la
grep
ligne de commande utilisée. Nous pouvons maintenant lire l’expression régulière plus facilement: elle correspond exactement de start (^
) à end ($
) de la ligne. L'expression entre eux correspond à n'importe quel caractère sauf newline, répété 42 fois. Combinées, il s’agit de lignes comportant exactement 42 caractères.Revenons maintenant aux commandes réelles du shell: L'
grep
option-E
(--extended-regexp
) permet de ne pas échapper à la{}
lisibilité. Option-m 1
(--max-count=1
) le fait s'arrêter après la première ligne. Le<
dans lawc
commande écrit le fichier dans son stdin, pour empêcher l'wc
impression du nom du fichier avec la longueur.Quelles lignes les plus longues?
Pour rendre les exemples plus lisibles avec le nom de fichier apparaissant deux fois, je vais utiliser une variable
f
pour le nom de fichier; Chacun$f
dans l'exemple pourrait être remplacé par le nom du fichier.Affiche la première ligne la plus longue - la première ligne aussi longue que la plus longue:
Afficher toutes les lignes les plus longues - toutes les lignes aussi longues que la ligne la plus longue:
Affiche la dernière ligne la plus longue - la dernière ligne aussi longue que la ligne la plus longue:
Afficher la ligne la plus longue unique - la ligne la plus longue plus longue que toutes les autres lignes, ou échouer:
(La dernière commande est encore plus inefficace que les autres, car elle répète la commande grep complète. Elle doit évidemment être décomposée de manière à ce que la sortie
wc
et les lignes écrites pargrep
soient enregistrées dans des variables.Notez que toutes les lignes les plus longues peuvent en réalité être toutes les lignes. Pour enregistrer dans une variable, seules les deux premières lignes doivent être conservées.)
la source
L'exemple suivant allait être, et aurait dû être, un commentaire sur la réponse de dmitry.malikov , mais à cause de l' utilisation inutile de l'espace de commentaire visible ici, j'ai choisi de le présenter ici, où il sera au moins visible. ..
Ceci est une simple variante de la méthode awk à passe unique de dmitry .
Il imprime toutes les lignes "égales les plus longues". (Remarque.
delete array
Est une extension gawk).la source
En pure bash:
la source
_max_line[0]=${_line}
ne supprime pas le reste des "lignes les plus longues" précédemment accumuléesunset _max_line
...J'ai développé un petit script shell pour cela. Il affiche la longueur, le numéro de ligne et le trait lui-même par longueur dépassant une taille donnée, telle que 80 caractères:
https://github.com/lordofrain/tools/blob/master/longest-line/longest-line.sh
la source
$*
est rarement une bonne idée, vous voulez"$@"
. Le/.*/
dans votreawk
ne fait rien car cela correspond aussi aux lignes vides. Vous pourriez éviter d’échapper à la\$0
citation simple'EOF'
. Pourquoi utiliser unBEGIN{}
bloc vide ? Enfin, vous n’avez pas besoincat
, simplementawk . . . "$file" | . . .
awk -vmax=15 '{len=length($0); if(len>=max){printf("%s, %d at line # %d %s\n", FILENAME, len, NR, $0);}}' file*
Vous pouvez utiliser
wc
:la source
wc -L
inconvénient.