Programmino shell, cosa non va?
Ragazzi secondo voi cosa c'è di errato nella sintassi di awk?
#!/bin/sh ################################################################################### #Si implementi uno script di shell che trova, a partire da una cartella radice, # #tutti file di tipo .txt, .rtf e .odt che al suo interno hanno le parole con le # #seguenti caratteristiche: # #-hanno il prefisso 'un'; # #-hanno almeno sei caratteri; # #-gli ultimi due caratteri sono delle vocali. # ################################################################################### clear if [ ! -d "$1" ] then echo "Errore nell'input" echo "Cartella inesistente" exit 1 else root_dir="$1" fi #Cerco tutti i file che hanno la data estensione! filetxt=`find $root_dir -name *.txt` filertf=`find $root_dir -name *.rtf` fileodt=`find $root_dir -name *.odt` #Concateno questi file in un unico file files="$filetxt $filertf $fileodt" for i in $files do cat $i | awk " ~ /^[un]*{6}[a|e|i|o|u]$/" done
Risposte
Proverei a usare i singoli apici e un
L'espressione regolare però non mi sembra corretta, inoltre devi trovare quali file contengono quelle parole o visualizzare le parole trovate?
$0prima dell'operatore
~, così:
cat $i | awk '$0 ~ /^[un]*{6}[a|e|i|o|u]$/'
L'espressione regolare però non mi sembra corretta, inoltre devi trovare quali file contengono quelle parole o visualizzare le parole trovate?
"anonymous_be1147":
Proverei a usare i singoli apici e un\( 0prima dell'operatore~, così:cat \)i | awk '\( 0 ~ /^[un]*{6}[a|e|i|o|u] \)/'
L'espressione regolare però non mi sembra corretta, inoltre devi trovare quali file contengono quelle parole o visualizzare le parole trovate?
Ma il fatto di mettere il pattern /^[un]*{6}[a|e|i|o|u]/
mi dice di prendere le parole che iniziano con un (^[un]) che sono composte da 6 o più lettere (*{6}) e che terminano con una vocale ([a|e|i|o|u]$). E' sbagliato secondo te?
comunque deve trovare quei file che contengono quelle parole, e non stampare le parole.
"fk16":
Ma il fatto di mettere il pattern /^[un]*{6}[a|e|i|o|u]/
mi dice di prendere le parole che iniziano con un (^[un]) che sono composte da 6 o più lettere (*{6}) e che terminano con una vocale ([a|e|i|o|u]$). E' sbagliato secondo te?
Dipende da cosa e dove vuoi cercare. Quell'espressione io la leggo così:
trova all'inizio della riga una lettera u oppure una lettera n, questa lettera può essere ripetuta zero o più volte, quello che hai trovato prima deve essere ripetuto 6 volte, quindi deve esserci una vocale oppure un carattere di pipe, alla fine della riga. E questo probabilmente non è quello che vuoi.
Io procederei così per "costruire" l'espressione regolare. Le parole da cercare devono avere almeno 6 caratteri.
i primi due caratteri devono essere una u seguita da una n

/un/, gli ultimi due devono essere vocali

/un[aeiou]{2}/. Siccome la parola deve essere lunga almeno 6 caratteri, in mezzo ci devono essere almeno due caratteri qualsiasi (alfanumerici)

/un[[:alnum]]{2,}[aeiou]{2}/.
Ora siccome si stanno cercando delle parole intere, bisogna considerare i confini delle parole (cio che segna l'inizio e la fine), altrimenti ci potrebbe essere corrispondenza su parti di parole più lunghe. Quindi l'espressione regolare finale diventerebbe
/\./
Ovviamente ci sono altri modi per scrivere quest'espressione, dipende in genere da quale implementazione di awk stai usando, e questo è solo uno spunto. Volendo ci sarebbero altre considerazioni da fare sullo script.
P.S. Se non devi per forza usare
awke
find, puoi comodamente ripiegare su
egrepche tramite le sue opzioni ti stampa il nome dei file dove c'è corrispondenza su tutta un directory specificata.
egrep -l '\<un[[:alnum:]]{2,}[aeiou]{2}\>' -r DIRECTORY_DA_ANALIZZARE
Innanzi tutto ti ringrazio del tuo aiuto, sei stato gentilissimo e mi è stato tutto molto chiaro!
Comunque se non ti è disturbo ti posso chiarimento su un'ultima cosa?
In pratica ho il seguente esercizo svolto nel seguente modo da me:
Ti spiego quale è il problema. In pratica Nel seguente ciclo for:
la i dovrebbe assumere i nomi dei file che cominciano con '.' , invece mi vengono presi tutti i file della certella passata come argomento. Mi potresti spiegare il motivo?
Comunque se non ti è disturbo ti posso chiarimento su un'ultima cosa?
In pratica ho il seguente esercizo svolto nel seguente modo da me:
#!/bin/sh ############################################################ #Scrivere uno script di shell, rmhid, che data una cartella# #radice di partenza elimini tutti i file e le cartelle # #nascoste al suo interno (le operazioni devono essere # #eseguite ricorsivamente all'interno delle sottocartelle # #della cartella radice). # #Ad esempio, rmhid /tmp elimina ricorsivamente tutti i file# #e le cartelle nascoste a partire dalla cartella /tmp. # ############################################################ #Controllo i paramentri if [ $# -ne 1 ] then echo "Errore nell'input" echo "Usare: $0 [directory]" exit 1 fi if [ ! -d $1 ] then echo "La directory non esiste" exit 1 else dir=$1 fi rmhid() { curr_dir="$1" for i in `ls -a $curr_dir/\.` do #per sicurezza simulo la rimozione con echo echo "Rimuovo il file $i" done for i in `ls $curr_dir/*` do if [ -d "$i" ] then echo "$i è una sotto directory" rmhid $i fi done } rmhid "$dir"
Ti spiego quale è il problema. In pratica Nel seguente ciclo for:
for i in `ls -a $curr_dir/\.` do #per sicurezza simulo la rimozione con echo echo "Rimuovo il file $i" done
la i dovrebbe assumere i nomi dei file che cominciano con '.' , invece mi vengono presi tutti i file della certella passata come argomento. Mi potresti spiegare il motivo?
Be', non funziona perché il punto indica come sai anche la directory corrente. Secondo me dovresti innanzitutto rimuovere le directory '.' e '..' dall'elenco usando l'opzione
Spiegazione nel caso non conoscessi l'espansione dei parametri: la stringa
A parte questo, c'è da dire che se le directory nascoste (cioè quelle che iniziano con un punto) vanno eliminate senza controllarne il contenuto, allora lo script si può semplificare moltissimo. Considera poi che forse è meglio passare
-Ainvece di
-a. Poi testare il nome di ogni file dell'elenco per accertarsi che inizi con un punto. Un modo abbastanza semplice per farlo è tramite l'istruzione:
if [ ".${i#.} != ".${i}" ]; then echo "Rimuovo il file ${i}" fi
Spiegazione nel caso non conoscessi l'espansione dei parametri: la stringa
".${i#.}"
è costituita da un punto seguito dal contenuto della variabile $iprivato del più piccolo prefisso
.(un punto). La seconda stringa,
".${i}"
, è costituita invece da un .seguito dal contenuto della variabile
$i. È chiaro quindi che se
$icontiene un valore che inizia con un punto allora le due stringhe saranno diverse e verrà eseguita la rimozione del file.
A parte questo, c'è da dire che se le directory nascoste (cioè quelle che iniziano con un punto) vanno eliminate senza controllarne il contenuto, allora lo script si può semplificare moltissimo. Considera poi che forse è meglio passare
$1/${i}sia al comando
rmche nella chiamate ricorsiva a
rmhid.