Domanda Trova e riporta i numeri di riga delle righe vuote nel file di testo


Ho un file di testo contenente oltre 14000 righe. contiene alcuni dati che sto usando per l'addestramento dei dati sul riconoscimento vocale.

Ho creato quel file tramite la codifica di Java e, a causa di qualche errore semantico, alcune linee sono vuote. Ogni volta che eseguo l'allenamento dà un errore dopo circa 30 minuti lamentando che c'è una linea vuota.

C'è qualche codice / script / comando che può darmi un elenco di numeri di riga con linee vuote, quindi posso riempire quelle righe vuote e salvare il mio tempo?

Il lavoro dovrebbe essere come:

Inserirò un file.txt e mi darà

line number 1121,1212,1450,13000 and so on ...  sono vuoti file.txt 

enter image description here


2
2017-08-06 18:18


origine


Ho rimosso i riferimenti a 16.10 in quanto questa domanda non è specifica per la versione di Ubuntu, ma per favore esegui l'upgrade in quanto 16.10 non è supportato (e off-topic qui) - Zanna
Sembra un problema XY; Come hai intenzione di riempire le linee vuote una volta che hai la lista? - steeldriver
sed -i '/^$/d' file volere Elimina linee vuote da file. Potrebbe essere una soluzione migliore per stampare solo numeri di linea ... - YSC
Non voglio rimuovere la linea vuota, ma piuttosto riempirli con valori corretti - Adnan Ali


risposte:


Puoi trovare le linee vuote e i loro numeri di riga con

grep -E --line-number --with-filename '^$' file.txt  

Un esempio:

w3@aardvark:~(0)$ grep -E --line-number --with-filename '^$' file.txt
file.txt:1:
file.txt:3:
file.txt:4:
w3@aardvark:~(0)$ cat -n file.txt
     1  
     2  Not empty
     3  
     4  
     5  Not empty
w3@aardvark:~(0)$ 

Se le righe "vuote" contengono spazi vuoti o tabulazioni, utilizzare:

grep -E --line-number --with-filename '^\s*$' file.txt

8
2017-08-06 18:42



Perché stai usando -E? bello anche se +1;) - Ravexina
Fa anche il lavoro: grep -n '^$' file.txt. Se vuoi solo i numeri, inserisci cut -d: -f1. - wjandrea
@Ravexina C'erano diversi grep programmi (grep, egrep, fgrep), ma la programmazione moderna li ha combinati in uno (ed è lo standard POSIX). -E dice grep a Interpret PATTERN as an extended regular expressionad esempio, comportati come il vecchio egrep. - waltinator
@waltinator Penso che quello che Ravexina si chiede sia il motivo per cui ti serve -E per un modello semplice come ^$. - muru
Sì, come dice muru, non stai usando alcun ERE, almeno nel tuo primo comando, quella era la mia domanda reale ... - Ravexina


sed riporterà il numero della linea con il = comando, in modo da poter usare questa espressione per riportare i numeri di riga delle linee vuote (linee senza nulla in mezzo ^ (inizio della linea) e $ (fine della riga)):

sed -n '/^$/=' file

Noi usiamo il -n opzione per sopprimere la stampa del flusso (i numeri di riga vengono stampati separatamente dalle linee stesse quando vengono utilizzati =, quindi non c'è p comando qui), quindi l'unico risultato sono i numeri di riga delle linee corrispondenti.

$ sed -n '/^$/=' foo 
1
3
5
7

(se le righe 1, 3, 5 e 7 sono vuote foo)


Ecco un esempio per mostrare come è possibile ottenere l'interazione dell'utente desiderata. Potresti usare qualsiasi soluzione al posto di sed espressione in queste strutture ...

$ cat foo

2

4

6

8

Così:

$ read -p "Enter file name: "; echo -e "The following lines are empty in "$REPLY":\n$(sed -n '/^$/=' "$REPLY" | tr '\n' ' ')"
Enter file name: foo
The following lines are empty in foo:
1 3 5 7 

(Uso tr '\n' ',' per ottenere virgole anziché spazi)

Potresti salvare come script (sto nominando il mio empline):

#!/bin/bash
read -p "Enter file name: "
echo -e "The following lines are empty in "$REPLY":\n\
$(sed -n '/^$/=' "$REPLY" | tr '\n' ' ')"

Rendi eseguibile lo script:

chmod u+x empline

Quindi puoi eseguirlo in questo modo

$ ./empline
Enter file name: foo
The following lines are empty in foo:
1 3 5 7 

Potresti saltare il read linea e sostituire "$REPLY" con "$1" utilizzare il nome file come parametro posizionale (quindi eseguire ./empline foo). Per semplificare l'utilizzo, puoi creare una funzione e aggiungerla alla fine del tuo ~/.bashrc:

function empline() {
    echo -e "The following lines are empty in "$1":\n\
$(sed -n '/^$/=' "$1" | tr '\n' ' ')"
}

Questo prende il nome del file come argomento:

$ empline foo
The following lines are empty in foo:
1 3 5 7 

7
2017-08-06 18:28



il file sed -n '/ ^ $ / =' non funziona - Adnan Ali
Hai dato il nome corretto del file? Ci sono dei personaggi sulle linee vuote? @AdnanAli - Zanna


utilizzando awk

Il metodo per più file di input (vedi fine del post) è il più robusto.

Input singolo file:

awk 'BEGIN { printf "Line numbers of empty lines in " ARGV[1] ": " } !NF { printf sep NR ; sep="," } END { printf "\n" }' file.txt

Il BEGIN la sezione viene eseguita prima che il file di input venga elaborato.

ARGV[1] è il nome del file di input. Questo corrisponde a awk FILENAME variabile, che non funziona nel BEGIN sezione.

!NF corrisponde a linee vuote o che contengono solo separatori di campo. I separatori di campo predefiniti sono spazi e caratteri di tabulazione, quindi le righe che contengono solo spazi e tabulazioni contano come vuote. NF (senza il punto esclamativo) corrisponde alle righe contenere dati e aggiunta !  inverte la partita.

NR è il numero di riga del file di input attualmente in fase di valutazione. NR non si reimposta su 1 se nella riga di comando sono specificati file di input aggiuntivi.

Per evitare che una virgola venga visualizzata di fronte al primo numero di riga corrispondente, lasciare la stringa sep indefinito fino a dopo la stampa della prima partita.

Il ENDla sezione viene eseguita dopo l'elaborazione del file di input. In questo esempio, termina l'output in modo pulito stampando un carattere newline in stile Unix.

Esempio di output:

Line numbers of empty lines in file.txt: 8,13,15,20,25,28

È un po 'sciatto usare un nome di stringa senza prima averlo impostato, anche se inizialmente volere deve essere vuoto È possibile impostare in modo esplicito il sep stringa per essere vuota nel BEGIN sezione:

awk 'BEGIN { sep="" ; printf "Line numbers of empty lines in " ARGV[1] ": " } !NF { printf sep NR ; sep="," } END { printf "\n" }' file.txt

Più file di input:

awk 'FNR==1 && NR>1 { printf "\n" } FNR==1 { sep="" ; printf "Line numbers of empty lines in " FILENAME ": " } !NF { printf sep FNR ; sep="," } END { printf "\n" }' file1.txt file2.txt file3.txt

FNR è simile a NR, tranne che il FNR il contatore del numero di riga si reimposta su 1 all'inizio di ciascun file.

La sezione FNR==1 && NR>1 { printf "\n" } causa la stampa di ogni file su una riga separata. Stampa un carattere di nuova riga quando la prima riga di ciascuno addizionale il file di input viene elaborato, ma non per la prima riga del file primo file.

Esempio di output:

Line numbers of empty lines in file1.txt: 8,13,15,20,25,28
Line numbers of empty lines in file2.txt: 1,2,4,6,7,9,10
Line numbers of empty lines in file3.txt: 3,8,9,11,13,15

6
2017-08-07 01:14



Probabilmente lo userò FNR == 1 e FILENAME invece di BEGIN e ARGV[1] (e FNR invece di NR, quindi dovrebbe funzionare con più file). - muru
@muru - Grazie! Ho aggiunto un metodo per l'immissione di più file in base al tuo suggerimento. - Gaultheria


Pure Bash, usando il file di esempio foo a partire dal La risposta di Zanna:

i=0
while read line; do
    ((++i))
    if [[ $line == '' ]]; then
        echo $i
    fi
done < foo

Produzione:

1
3
5
7

Oppure potresti preferire l'equivalente Bash di Soluzione Python utilizzando enumerate():

cat -n foo | 
    while read -r i line; do
       if [[ $line == '' ]]; then
            echo $i
        fi
    done

5
2017-08-06 18:43





perl:

Stampa (printf("%s\n", $.)) il numero di riga se è vuoto (if /^$/):

perl -ne 'printf("%s\n", $.) if /^$/' file.txt

python3:

Iterating over the numerated (start == 1) linee del file e stampa il numero di riga quando vuoto:

with open('file.txt') as f:
    for idx, line in enumerate(f, 1):
        if line.rstrip('\n') == "":
            print(idx)

3
2017-08-07 03:48



non so come eseguire script perl in Ubuntu - Adnan Ali
@AdnanAli perl arriva di default con Ubuntu. Nel tuo caso d'uso, esegui semplicemente il modo in cui ho fatto o, se ti va, usa uno script con #!/usr/bin/env perl essere lo shebang. - heemayl
non mostra nulla. Ho appena controllato. lo script perl non funziona - Adnan Ali
@AdnanAli Modifica la tua domanda e aggiungi un esempio di input. - heemayl


Per un singolo file eseguito:

$ printf "line numbers %s are empty in your file.\n"\
 "$(grep --line-number '^$' file-name | tr ':\n' ', ')"

Quali uscite:

line numbers 2, 5, 7, 9, 10,  are empty in your file.

2
2017-08-07 01:54