2011-11-03 25 views
12

Ho una cartella chiamata foo. Foo ha altre cartelle che potrebbero avere sottocartelle e file di testo. Voglio trovare tutti i file che iniziano con l'anno del nome e leggere la sua ennesima riga e stamparla in un nuovo file. Ad esempio, foo ha un file chiamato year1 e le sottocartelle hanno file chiamati year2, year3 ecc. Il programma stamperà la prima riga dell'anno1 in un file chiamato writeout, quindi stamperà la seconda riga dell'anno2 sul file writeout ecc.Come si legge l'ennesima riga di un file e lo si stampa su un nuovo file?

Inoltre non ho davvero capito come eseguire un ciclo for per un file.

Finora ho:

#!/bin/bash 

for year* in ~/foo 
do 
    Here I tried writing some code using the sed command but I can't think of something  else. 
done 

ho anche ottenere un messaggio nel terminale che dice `anno *' non è un identificatore valido. Qualche idea?

+0

La prego di accettare una delle risposte qui sotto come credo hanno fornito informazioni sufficienti a questa domanda? –

risposta

0

L'attività ha due attività secondarie: trova il nome di tutti i file dell'anno, quindi estrae la riga N. Considera il seguente script:

for file in `find foo -name 'year*'`; do 
    YEAR=`echo $file | sed -e 's/.*year\([0-9]*\)$/\1/'` 
    head -n $YEAR $file | tail -n 1 
done 

La chiamata di ricerca trova i file corrispondenti per te nella directory foo. La seconda riga estrae solo le cifre alla fine del nome file dal nome file. La terza riga estrae quindi le prime N righe dal file, mantenendo solo l'ultima delle prime N righe (leggi: solo la riga N).

+0

Dovrei vedere qualcosa sul mio schermo? Perché ottengo solo una riga vuota. – captain

5

Ecco un modo per farlo:

awk "NR==$YEAR" $file 
+0

Ricevo il messaggio: newline inattesa o fine stringa. – captain

+0

quindi $ YEAR è una stringa vuota o non un numero ... –

3

Usa find per individuare i file che si desidera, e quindi sed per estrarre ciò che si vuole:

find foo -type f -name year* | 
while read file; do 
    line=$(echo $file | sed 's/.*year\([0-9]*\)$/\1/') 
    sed -n -e "$line {p; q}" $file 
done 

Questo approccio:

  • Utilizzare find per produrre un elenco di file con un nome che inizia w con la stringa "anno".
  • Pipes l'elenco di file per un ciclo while per evitare lunghe comando
  • Utilizza sed per estrarre il numero di riga desiderato dal nome del file
  • Utilizza sed per stampare solo la linea desiderata e quindi chiudere immediatamente. (È possibile lasciare il q e basta scrivere ${line}p che avrebbe funzionato, ma essere potenzialmente meno efficiente di $file è grande. Inoltre, q non possono essere pienamente supportato su tutte le versioni di sed.)

Non funzionerà correttamente per i file con spazi nei loro nomi però.

+0

Ottengo messaggi dicendo: sed: -e espressione # 1, carattere 7: comando sconosciuto: 'k ' – captain

+0

Puoi incollare l'output del comando dopo, eseguendo "set -x" per abilitare il debug? –

+0

Scusa ma non capisco cosa devo fare. Sono un principiante. – captain

28

Sed può aiutarti.

Ricordare che sed in genere elabora tutte le righe in un file E stampa ogni riga nel file.

È possibile disattivare questa funzione e disporre di sed solo linee di stampa di interesse facendo corrispondere un modello o un numero di linea.

Così, per stampare la seconda riga del file 2, si può dire

sed -n '2p' file2 > newFile2 

Per stampare la seconda linea e poi interrompere l'elaborazione aggiungere il q (per uscire) di comando (è necessario anche parentesi per raggruppare il 2 comandi insieme), vale a dire

sed -n '2{p;q;}' file2 > newFile2 

(se si elaborano file di grandi dimensioni, questo può essere il salvataggio di un bel tempo).

a fare quel più generale, è possibile cambiare il numero ad una variabile che conterrà un numero, cioè

lineNo=3 
    sed -n "${lineNo}{p;q;}" file3 > newFile3 

Se si desidera che tutte le linee di fette di andare in uno dei file, quindi utilizzare i gusci 'append-reindirizzamento', vale a dire

for lineNo in 1 2 3 4 5 ; do 
    sed -n "${lineNo}{p;q;}" file${lineNo} >> aggregateFile 
done 

gli altri messaggi, con l'utilizzo dei risultati della find ... per guidare il filelist, sono un ottimo approccio.

Spero che questo aiuti.

+0

La sintassi di raggruppamento funziona in GNU sed. –

+0

@glennjackman: non sono sicuro del tuo punto. La sintassi di raggruppamento funziona anche su AIX e su Solaris, e per quanto ne so, fa parte del design originale di sed. Grazie per il feedback :-) – shellter

+0

Se ti piace Python over sed puoi ... 'python -c" import sys; print (sys.stdin.readlines() [int (sys.argv [1]) - 1]) .strip() "" (o, naturalmente, definire un alias per quella cosa grande) – hangtwenty

0
1.time head -5 emp.lst tail -1 
It has taken time for execution is 
real 0m0.004s 
user 0m0.001s 
sys 0m0.001s 

or 

2.awk 'NR==5' emp.lst 
It has taken time for execution is 
real 0m0.003s 
user 0m0.000s 
sys 0m0.002s 

or 

3.sed -n '5p' emp.lst 
It has taken time for execution is 
real 0m0.001s 
user 0m0.000s 
sys 0m0.001s 

or 

4.using some cute trick we can get this with cut command 
cut -d “ 
“ -f 5 emp.lst 
# after -d press enter ,it means delimiter is newline 
It has taken time for execution is 
real 0m0.001s 
+1

Mentre la tua risposta può risolvere la domanda, è sempre meglio se puoi fornire una descrizione di quale fosse il problema e come la tua risposta lo risolva . Questo è un suggerimento per migliorare ulteriormente questa e le future risposte. –

+1

Puoi approfondire come funziona la tua risposta? –

1

Il modo migliore che funziona sempre, a patto di fornire 2 argomenti:

$ touch myfile 
$ touch mycommand 
$ chmod +x mycommand 
$ touch yearfiles 
$ find/-type f -name year* >> yearfiles 
$ nano mycommand 
$ touch foo 

Tipo questo:

#/bin/bash 
head -n $1 $2 >> myfile 
less -n 1 myfile >> foo 

Usa ^X, y e Invio per salvare. Quindi eseguire myCommand:

$ ./mycommand 2 yearfiles 
$ cat foo 
year2 

presumendo i file year sono:

year1, year2, year3 

Inoltre, ora avete l'installazione, basta usare $ ./mycommand LINENUMBER FILENAME da ora in poi.

0

Qui si va

sed ${index}'q;d' ${input_file} > ${output_file} 
Problemi correlati