2009-06-10 11 views
9

Mam plik dziennika, który zawiera liczbę linii o błędach, takich jak:Czy możesz grep pliku za pomocą wyrażenia regularnego i wyprowadzać tylko pasujące części linii?

Failed to add [email protected] to database 

mogę filtrować te linie za pomocą jednego wywołania grep:

grep -E 'Failed to add (.*) to database' 

Działa to dobrze, ale co ja Naprawdę lubię robić grep (lub inne polecenie Unix, do którego wysyłam dane wyjściowe) tylko wyprowadzić część adresu e-mail dopasowanej linii.

Czy to możliwe?

Odpowiedz

5

Można użyć sed:

grep -E 'Failed to add (.*) to database'| sed 's/'Failed to add \(.*\) to database'/\1' 
+4

Korzystanie z opcji -o grep jest prostsze ... – bortzmeyer

+0

-o nie wystarcza jednak to jest? ref: http://stackoverflow.com/a/1140415/32453 – rogerdpack

+0

@rogerdpack: Wygląda na to, że masz rację. '-o' zwróci zestaw ciągów" Nieudane dodanie *[email protected]* do bazy danych ", podczas gdy PO tylko chce * [email protected]*. –

1

lub Python:

cat file | python -c "import re, sys; print '\r\n'.join(re.findall('add (.*?) to', sys.stdin.read()))" 
15

sed jest w porządku bez grep:

sed -n 's/Failed to add \(.*\) to database/\1/p' filename 
+0

Z pewnością mógł też użyć awk !! – RandomNickName42

+0

sed może to zrobić w jednym poleceniu ... – rogerdpack

2

To powinno załatwić sprawę:

grep -x -e '(?<=Failed to add).+?(?= to database)' 

Korzysta z pozytywnego potwierdzenia, poprzedzonego dopasowaniem adresu e-mail, po którym następuje asercja postivie look-behind. Zapewnia to, że pasuje do całej linii, ale tylko faktycznie zużywa (i w ten sposób zwraca) część adresu e-mail.

Opcja -x określa, że ​​grep powinien pasować do linii, a nie do całego tekstu.

-1

Jeśli chcesz używać grep, bardziej odpowiednie byłoby użycie egrep;

About egrep 

Search a file for a pattern using full regular expressions. 

grep nie zawsze będzie miał pełną funkcjonalność dla regex.

+1

Już używa egrep, ponieważ używa -E. Nie ma nic wspólnego z problemem, który kontroluje wyjście. – bortzmeyer

+0

O czym ty mówisz?Jeśli zobaczysz "tag", pyta o * UNIX * grep, który nie jest (jak sugerujesz) GNU-Everywhere, odnieś się do http://www.softpanorama.org/Tools/Grep/grep_reference.shtml dla niektórych przegląd różnych wersji grep na UNIX (NIE GNU GREP), co zobaczysz w czerni i bieli, "Limited regex - grep", "Extended regex - egrep". Zatem _REGARDLESS_ z faktu, że GNU grep może być (jest) lepszy, nie będzie to coś, na co możesz zawsze liczyć, być wdrożonym i być dostępnym dla wszystkich twoich skryptów. Całe moje zdanie jest takie, że nie możesz liczyć na grep "basic" – RandomNickName42

+0

Nie widzę sensu. OP nie powiedział nic o systemie operacyjnym, z którego korzysta, z wyjątkiem "Unixa". Więc może to być Unix gdzie GNU grep jest domyślny (na przykład Debian) lub Unix gdzie GNU grep może być zainstalowany natychmiast za pomocą jednego polecenia (NetBSD z pkg_add textproc/grep) – bortzmeyer

2

Najnowsze wersje GNU grep mają opcję -o, która robi dokładnie to, co chcesz. (-o jest dla --only-matching).

+4

używając '-o' wyświetli dopasowaną część aby wyreperować insted z całej linii, w której znaleziono dopasowanie. ale @Olly chciał tylko pierwszą podgrupę (adres e-mail, bez otaczającego tekstu). –

3

Można również rury grep tylko do siebie :)

grep -E 'Failed to add (.*) to database' | grep -Eo "[^ ][email protected][^ ]+" 

Lub, jeśli „linie w interesie” są jedynymi z e-maili, wystarczy użyć ostatnie polecenie grep bez pierwszego.

-1

-r rozwiązaniem dla sed pozwala wyrażenia regularne bez ukośników

sed -n -r 's/Failed to add (.*) to database/\1/p' filename 
Powiązane problemy