2012-11-14 8 views
55

Sto provando ad estrarre il tempo da una stringa usando bash, e sto facendo fatica a capirlo.Estrai la sottostringa usando regexp in plain bash

mia stringa è come questo:

US/Central - 10:26 PM (CST) 

e voglio estrarre la parte 10:26.

Qualcuno sa di un modo per farlo solo con bash - senza usare sed, awk, ecc.?

Come, in PHP userei - non il modo migliore, ma funziona - qualcosa come:

preg_match(""(\d{2}\:\d{2}) PM \(CST\)"", "US/Central - 10:26 PM (CST)", $matches); 

Grazie per qualsiasi aiuto, anche se la risposta utilizza sed o awk

risposta

132

Utilizzando puro :

$ cat file.txt 
US/Central - 10:26 PM (CST) 
$ while read a b time x; do [[ $b == - ]] && echo $time; done < file.txt 

un'altra soluzione con bash regex:

$ [[ "US/Central - 10:26 PM (CST)" =~ -[[:space:]]*([0-9]{2}:[0-9]{2}) ]] && 
    echo ${BASH_REMATCH[1]} 

un'altra soluzione utilizzando grep e guardare intorno avanzata regex:

$ echo "US/Central - 10:26 PM (CST)" | grep -oP "\-\s+\K\d{2}:\d{2}" 

un'altra soluzione utilizzando sed:

$ echo "US/Central - 10:26 PM (CST)" | 
    sed 's/.*\- *\([0-9]\{2\}:[0-9]\{2\}\).*/\1/' 

un'altra soluzione utilizzando Perl:

$ echo "US/Central - 10:26 PM (CST)" | 
    perl -lne 'print $& if /\-\s+\K\d{2}:\d{2}/' 

e ultimo con awk:

$ echo "US/Central - 10:26 PM (CST)" | 
    awk '{for (i=0; i<=NF; i++){if ($i == "-"){print $(i+1);exit}}}' 
+0

Cool! Qualche possibilità che io usi anche il trattino "-" nel pattern? perché quel grep restituisce alcune corrispondenze, e mi interessa solo quello che ha il trattino e quindi uno spazio e poi il tempo ..... – andrux

+0

Post modificato di conseguenza –

+0

Aggiunta un'altra soluzione –

15

rapida 'n sporca,-regex libera, a basso robustezza tecnica chop chop-

string="US/Central - 10:26 PM (CST)" 
etime="${string% [AP]M*}" 
etime="${etime#* - }" 
+2

È così disgustosamente sporco che mi vergogno di non aver pensato a me stesso. +1 '| read area dash time apm zone' funziona anche – Orwellophile

+0

Molto pulito ed evita le chiamate a programmi esterni. –

46
echo "US/Central - 10:26 PM (CST)" | sed -n "s/^.*-\s*\(\S*\).*$/\1/p" 

-n  suppress printing 
s  substitute 
^.*  anything at the beginning 
-  up until the dash 
\s*  any space characters (any whitespace character) 
\(  start capture group 
\S*  any non-space characters 
\)  end capture group 
.*$  anything at the end 
\1  substitute 1st capture group for everything on line 
p  print it 
+0

Benvenuti in StackOverflow! Spiacente, ho accidentalmente segnalato questo come "non-risposta". Sfortunatamente non c'è modo di sganciare, ma quella bandiera verrà presto rifiutata da un moderatore. –

+0

Grazie per il benvenuto. Nessun problema con la bandiera "non-risposta". – jgshawkey

+5

Mi sembra che questo mi abbia reso un padrone istantaneo. Una buona opzione che posso modificare è meglio di nove non capisco. – Noumenon