2012-11-14 12 views
55

Próbuję wyodrębnić czas z ciągu znaków za pomocą basha i trudno mi go rozgryźć.Wyodrębnianie podłańcuchów za pomocą wyrażeń regularnych w zwykłym bashu

Mój łańcuch jest tak:

US/Central - 10:26 PM (CST) 

I chcę, aby wyodrębnić 10:26 część.

Ktoś wie, jak to zrobić tylko z bashem - bez użycia sed, awk, etc?

Podobnie jak w PHP użyłbym - nie jest najlepszym sposobem, ale działa - coś takiego:

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

Dzięki za pomoc, nawet jeśli odpowiedź używa sed lub awk

Odpowiedz

132

Korzystanie czysty :

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

innym rozwiązaniem z bash regex:

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

inne rozwiązanie używając grep i spojrzeć wokół zaawansowany regex:

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

Innym rozwiązaniem przy użyciu sed:

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

inne rozwiązanie przy użyciu Perl:

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

i ostatni przy użyciu awk:

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

Cool! Czy jest szansa, że ​​użyję również łącznika "-" we wzorze? ponieważ grep zwraca kilka dopasowań i interesuje mnie tylko ten, który ma łącznik, a następnie spację, a następnie czas ... – andrux

+0

Post edytowane odpowiednio –

+0

Dodano inne rozwiązanie –

15

Szybkie „n brudny, regex wolna, nisko solidność technika Chop-Chop

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

To jest tak obrzydliwie brudne, że wstydzę się, że sam o tym nie pomyślałem. +1 '| odczyt strefy czasowej strefy APM działa również – Orwellophile

+0

Bardzo czysty i unika połączeń z zewnętrznymi programami. –

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

Witamy w StackOverflow! Niestety, przypadkowo oznaczyłem to jako "nie-odpowiedź". Niestety nie ma możliwości odepchnięcia flagi, ale ta flaga zostanie wkrótce odrzucona przez moderatora. –

+0

Dzięki za powitanie. Bez obaw o flagę "nie jest odpowiedzią". – jgshawkey

+5

Czuję, że dzięki temu stałem się natychmiastowym mistrzem sed. Jedna dobra opcja, którą mogę poprawić, jest lepsza niż dziewięć, których nie rozumiem. – Noumenon

Powiązane problemy