Come posso identificare le righe nei file per una certa lunghezza


12

Vorrei trovare righe nel mio codice che superino una certa lunghezza. Il mio codice è in più file. Qual è un buon modo per farlo?

Mi piacerebbe conoscere i file e i numeri di riga; il contenuto sarebbe preferito, ma non necessario. Lo scopo dell'esercizio è quindi quello di capire come interrompere le linee (probabilmente manualmente).


Come vuoi i risultati? Come le linee stesse (il loro contenuto, come in grep), o come numeri di riga, o come qualcos'altro (forse vuoi applicare un'altra azione su di esse)? Probabilmente il modo più conveniente per farlo dipende da cosa verrà fatto con queste righe in seguito.
imz - Ivan Zakharyaschev,

@ imz - IvanZakharyaschev Buon punto. Domanda aggiornata.
Marcin,

Risposte:


13

Con grep:

grep -En '.{12}' file

Per righe di almeno 12 caratteri.

Con diversi file:

find . -type f -exec grep -En '.{12}' {} +

Alcune grepimplementazioni come GNU grep, possono eseguire autonomamente la ricerca dei file.

grep -rEn '.{12}' .

Ma attenzione ai collegamenti simbolici e ad altri file non regolari.


Mi piace perché è semplice e speravo di fare qualcosa del genere (non ci sono ancora riuscito).
Marcin,

12

Soluzione AWK

awk '{       
if (length($0) > 5)
        print $0;'} yourfile

O, più concisamente:

awk 'length > 5' file

9
Possiamo abbreviare la tua versioneawk 'length > 5'
cuonglm,

Gnouc è un killer del tutore;)
Ouki,

1
+1 perawk 'length > 5'

3
Con GNU awkun po 'meno elegante ma concisoawk '/^.{6,}/'
iruvar il

3
@ 1_CR, Questo è POSIX e può essere abbreviato awk '/.{6}/'(in realtà GNU awk fino a poco tempo fa era quello in cui non avrebbe funzionato a meno che non si passasse POSIXLY_CORRECT al suo ambiente).
Stéphane Chazelas,

5

Dal momento che l'unica cosa che mancava era una sedsoluzione

sed -n '/^.\{6,\}/p' file

5

Soluzione Bash

#!/bin/bash

count=0

while read; do
    ((++count)) 
    len=${#REPLY}
    if ((len > 80)); then
        echo "Line $count is $len characters."
    fi
done

Quindi, ad es ./whatever.sh < input.file. Questo non include la nuova riga sottraendo 1 da $len; se ciò non è desiderabile o se l'input utilizza terminazioni CRLF, è necessario adeguarsi di conseguenza.


1
perché non ${#line}evitare la exprforcella?
Iruvar,

1
ah ah, +1 per la bashsoluzione pura . Ma tieni presente che a meno che non ti attacchi IFS=davanti read, gli spazi iniziali verranno ignorati.
Iruvar,

1
Aggiunte alcune buone pratiche di base. Inoltre, tieni presente che la nuova riga non viene presa in considerazione, $linequindi non è necessario sottrarla.
Iruvar,

2
@ 1_CR in realtà se non dai readun nome in cui leggere, verrà letto REPLYe includerà tutti gli spazi bianchi. Nessuna IFSimpostazione necessaria.
Kojiro,

2
Sarà estremamente lento e gestirà in modo speciale i personaggi con la barra rovesciata. while readi cicli per elaborare il testo sono davvero cattive pratiche.
Stéphane Chazelas,

4

Con perl(ad esempio), supponendo che tu stia cercando righe più lunghe di 80 caratteri:

Per visualizzare le linee:

$ perl -nle 'print if length > 80' your_file

Per visualizzare il numero di righe:

$ perl -nle 'print "$.\n" if length > 80' your_file

O entrambi:

$ perl -nle 'print "[$.]:  $_\n" if length > 80' your_file

3
È necessario aggiungere la -lriga di comando, perlconterà l'interruzione di riga nelle righe.
cuonglm,

1

Rubino:

ruby -lne 'puts $_ if $_.size > 5' intputfile

Python:

python -c "import sys;[ sys.stdout.write(''.join(line)) for line in sys.stdin if len(line.strip()) > 5 ]" < inputfile

1

Ecco un'altra soluzione bash (bash 4):

minlen=5 # minimum length of a line
mapfile -tO1 < inputfile # Map the file to the array MAPFILE (by default)
                         # Start the array at index 1
for i in "${!MAPFILE[@]}"; do
  (( ${#MAPFILE[i]} > minlen )) || unset MAPFILE[i] # Remove shorter elements
done

La matrice risultante è scarsa, quindi gli indici di matrice vengono mantenuti. Da quando abbiamo iniziato da 1, gli indici sono i numeri delle linee che abbiamo mantenuto. Possiamo produrre solo quei numeri di riga:

printf 'Long lines found at: '
printf '%d, ' "${!MAPFILE[@]}"
echo

Oppure possiamo emettere le linee stesse:

printf '%s\n' "${MAPFILE[@]}"
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.