2015-06-24 35 views
5

Sto provando a leggere un file di testo riga per riga usando Shell Scripting. Quello che ho fatto èLeggere un file di testo riga per riga e controllare se quella linea ha una certa stringa

while read line 
do 
    var1=$(grep -s "Completed" $line) 
    var2=$(grep -s "Script Finished" $line) 

if[ "$var1" = "$line" ] 
    break 
else 
    if[ "$var2" = "$line" ] 
     count='expr $count + 1' 
    else 
     countinue 
    fi 
fi 
done < file.txt 

Se avete qualche suggerimento fatemelo sapere! Sono aperto ad altre opzioni perché ho cercato di farlo in questo modo troppo a lungo.

per chiarire:

sto attraversando un file riga per riga (while) allora sono grep che la linea per vedere se "Completato" è una stringa e grep per vedere se "Script finito" è una sottostringa (Grep imposterà la variabile sull'intera riga). Quindi, quando eseguo i controlli se la variabile è completata, voglio uscire dal ciclo while se non controllo se "Script Finished" è una sottostringa in modo da poter incrementare un contatore (sto cercando di contare quanti script sono stati completati prima di " Completare").

CIRCA CONFUSO:

quando faccio var1 = $ (grep -s "Completato" $ line) perché lo fa trovare tutte le istanze di Completato ... Ho pensato che se im passando riga per riga esso troverà solo le istanze in quella determinata linea.

EDIT:

ho usato la risposta awk di seguito. Tutto quello che dovevo fare è rimuovere l'istruzione {next} e funziona perfettamente.

Grazie

+2

Cosa stai cercando di ottenere con questo? Potresti fornire qualche informazione al riguardo? –

+0

Sì, certo, mi scuso. Sto cercando di passare attraverso un file che elenca quando vengono eseguiti gli script. Quindi mi interessa solo se uno script è finito .. se è finito, incrementerò il contatore. Tuttavia, gli script vengono eseguiti in blocchi .. mattina pomeriggio e notte. Quindi sto rompendo il ciclo con "blah blah" (Script completati) perché quella sarà la quantità di script finita al mattino – Alan

+2

Avrai un tempo molto più facile sia nel fare ciò che trovare risorse rilevanti se non provi a fare tutto in una volta, e invece concentrarsi sul rendere le singole parti di lavoro. Ad esempio, dovresti definire due stringhe 'a =" ciao mondo "b =" panda "' e provare a scrivere un'istruzione if che li confronta (e quindi impostare 'b = $ a' per assicurare che i casi sia positivi che negativi funzionino). È molto più semplice google "come faccio a confrontare le stringhe in uno script di shell" rispetto a "come faccio a leggere un file di testo riga per riga controllando se quella linea ha una determinata stringa". –

risposta

4

Hai diversi errori. Inoltre potresti voler considerare uno strumento che è pensato per fare questo genere di cose. awk è uno di quegli strumenti.

awk '/blah blah/ {exit} 
    /Finished/ {count+=1} 
    {next} 
    END{ print count} ' filename 

La prima riga si chiude quando corrisponde a "blah blah" in qualsiasi punto della linea.

La seconda riga conta il numero di partite "Finite".

Il {next} bit è lì per continuare a leggere e non stampare ogni riga - questo accade in alcune versioni di awk.

L'ultima riga, funzione END {}, viene eseguita quando il codice completa il file. Visualizza il valore del conteggio.

Ho scelto l'approccio awk piuttosto che provare a correggere gli errori di logica e di sintassi nello script della shell. Se hai bisogno di questo tipo di aiuto, considera la possibilità di riprodurre quasi tutti i blocchi (o linee) di codice da solo sulla riga di comando. Suppongo che tu abbia usato bash.

Errori esempi

-eq to compare strings, use =, example: [ "$var" = "something" ] 
$(var1) should be either "${var1}" or "$var1" lines 4 and 8 

grep restituisce una intera linea, stai testando "bla bla" e in attesa solo e soltanto appena "bla bla", come l'intero risultato?

+0

Ho intenzione di provare questo adesso .. Grazie per la risposta Vi farò sapere cosa succede. Sto testando la linea grep blah blah $ contro $ line .. Ma la tua strada sembra molto meglio. Ho sentito che awk può facilmente sostituire grep. – Alan

+0

"awk"/Completato/{exit} /Terminato/{count + = 1} {next} END {print count} 'filename' sembra essere in un ciclo infinito – Alan

+0

Ottenuto! Grazie mille. – Alan

2

Errore # 1:

Quando io var1 = $ (grep -s "Completato" $ riga) Perché ci trovo tutte le istanze di Completato

Nel comando riportato sopra grep si aspetta che $line sia un nome file e non una stringa. Se si desidera passare stringa è necessario utilizzare il tubo:

var1=$(echo "$line" | grep -s "Completed") 

O in Bash è possibile utilizzare stringa di reindirizzamento:

var1=$(grep -s "Completed" <<<"$line") 

Errore # 2:

Ci dovrebbe essere spazio tra if e [ ([ è test comando)


Questo comando grep probabilmente farà lo stesso che si sta tentando di fare con quel codice:

grep -v "Completed" file.txt | grep -c "Script Finished" 

grep -v "Completed" file.txt restituisce le righe che non contengono "Completato" e invia alla prossima grep attraverso il tubo che restituisce il numero di righe che contengono il testo "Script Finished".

+1

Grazie per i chiarimenti. E un modo intelligente di usare il grep. – Alan

1

Sto postando questo dopo la soluzione (corrente) accettata perché la soluzione accettata è in una lingua che non è coperta dai tag.

È possibile eseguire la stessa operazione in shell utilizzando un'istruzione case. (anche se per file di grandi dimensioni, awk o grep possono essere più veloce)

while read line; do 
case "$line" in 
    *"Completed"*)break;; 
    *"Script Finished"*)count=$((count + 1));; 
esac 
done < file.txt 

nota: questa forma di while read line; ... ometterà l'ultima riga, se questo non è ok, utilizzare while read line || [ "$line" ] (Questo è 1 motivo per cui alcuni IDE aggiungeranno una nuova riga vuota alla fine dei file)

+0

Oh non l'ho capito! Grazie – Alan