[Shell] egrep und reguläre Ausdrücke

ClausVB

Registered User
Ich habe unter "/etc/bind" (Debian, Kernel 2.6.18-4-686) verschiedene HOSTS-Dateien liegen mit DNS-Konfigurationen.

Ein "grep 20080701 /etc/bind/*.hosts" liefert mir
Code:
/etc/bind/meine-arge.de.hosts:                     2008070100
/etc/bind/die-beratung.de.hosts:                       2008070100

Ich möchte nur angezeigt bekommen:
Code:
meine-arge.de
die-beratung.de

Mit Perl und dem regulären Ausdruck
Code:
if ($_ =~ '\/etc\/bind/([\w-]+.[a-z]+).hosts')
kann ich dann auf die Variable $1 zugreifen. Ich möchte für solche Zwecke aber nicht immer ein Perl-Skript schreiben.

Mit "egrep" liefern die Versionen
Code:
egrep '/etc/bind/([\w-]+\.[a-z]+)\.hosts' test_egrep.txt
egrep '/etc/bind/([\w-]+\.[a-z]+)\.hosts' test_egrep.txt $1
egrep '/etc/bind/([\w-]+\.[a-z]+)\.hosts' $1 test_egrep.txt
keine Ergebnisse.

Was mache ich da falsch?

Zur Info: Tests wie
Code:
server:/etc# egrep 'media|proc' /etc/fstab
proc            /proc           proc    defaults        0       0
/dev/hdc        /media/cdrom0   iso9660 ro,user,noauto  0       0
/dev/fd0        /media/floppy0  auto    rw,user,noauto  0       0
server:/etc#
funktionieren.

Ich schau jetzt mal, ob man Output von "egrep" mit Perl weiterverarbeiten kann (auf Kommandozeile, ohne Skript).

Danke und Gruß
Claus

[EDIT] Das Beispiel habe ich abgewandelt aus der Linuxfibel von linwiki.org übernommen. Die Grundlagen dort habe ich ebenfalls gelesen.
 
Last edited by a moderator:
Noch eine Frage: Warum liefert ein
Code:
egrep '[a-z]+-[a-z]+-[a-z]+.de' *.hosts
etwas anderes als
Code:
egrep '[\w]+-[\w]+-[\w]+.de' *.hosts
denn letzteres liefert nicht einen Treffer.

Im SELFHTML steht
"/\w/ = eins der Zeichen vom Typ Buchstabe, vom Typ Ziffer oder einen Unterstrich enthält - (fast) genau wie (9.); ob Umlaute erkannt werden können, hängt von der Systemkonfiguration ab"

Ich würde jetzt erwarten, dass "[a-z]" zwar nur Kleinbuchstaben sucht, aber bei "\w" würde ich erwarten, dass Kleinbuchstaben auch dazugehören. Ich meine, das wäre bei Perl so ...

Danke und Gruß
Claus
 
Ok, für die Shell habe ich jetzt eine Lösung, die aber nicht so komfortabel ist:

Code:
server:/etc/bind# for i in `grep -c 20080703 * | grep -v :0 | cut -f1 -d: 
| sed 's,\.hosts$,,g'`; do echo looking up $i; dig $i; done > /root/zonen_test.txt

An einer richtigen Lösung mit regulären Ausdrücken und $1 wäre ich aber noch interessiert.

Gruß
Claus
 
Das Problem ist, dass nicht jedes Programm die Reguläre Ausdrücke gleich behandelt. Daher funktioniert das, was bei einem so funktioniert, beim anderen nicht unbedingt...

Ansonsten muss es ja nicht immer gleich Perl zum Nachbearbeiten sein, sondern Du kannst dafür auch einfach "cut" verwenden. Wenn Du ohne Nachbearbeitung auskommen willst, geht es auch mit "awk"
Code:
awk '/RE/ {print $1}' Datei
oder so ähnlich...
 
egrep tut nicht, was du willst.
sed lässt sich dafür super benutzen. Natürlich ist die sed-Syntax anzuwenden:
Code:
grep 20080701 /etc/bind/*.hosts|sed -e 's@.*bind/\(.*\)\.hosts.*@\1@'
 
Danke für die vielen Tipps und den Hinweis auf SED.

Folgende kurze (selbst gebastelte) Version funktioniert sehr gut:

Code:
grep -c 20080703 /etc/bind/* | grep -v :0 | sed 's,.*/\(.*\)\.hosts.*,\1,g'

Die von Elias ist noch kürzer und noch besser. Danke, Elias!

Problem gelöst.

Danke und Gruß
Claus
 
Last edited by a moderator:
Noch als Rückmeldung: Mit AWK komme ich nicht durch die Tür, aber da müsste ich wahrscheinlich nur die Doku intensiver lesen, um meinen Fehler zu finden ...

Test-Datei:
Code:
server:~/cvb# more test_egrep_forum.txt
/etc/bind/meine-arge.de.hosts:                  2008070100
/etc/bind/die-beratung.de.hosts:                        2008070100
/etc/bind/bergische2.de.hosts:                  2008070100
/etc/bind/bergische2.eu.hosts:                  2008070100

Die RegEx liefern alle das Gleiche:
Code:
server:~/cvb# awk '/.+/ {print $1}' test_egrep_forum.txt
/etc/bind/meine-arge.de.hosts:
/etc/bind/die-beratung.de.hosts:
/etc/bind/bergische2.de.hosts:
/etc/bind/bergische2.eu.hosts:
server:~/cvb# awk '/\/etc.+[a-z-]+\.[a-z]+/ {print $1}' test_egrep_forum.txt
/etc/bind/meine-arge.de.hosts:
/etc/bind/die-beratung.de.hosts:
/etc/bind/bergische2.de.hosts:
/etc/bind/bergische2.eu.hosts:
server:~/cvb# awk '/([a-z-]+)(\.)([a-z]+)/ {print $1}' test_egrep_forum.txt
/etc/bind/meine-arge.de.hosts:
/etc/bind/die-beratung.de.hosts:
/etc/bind/bergische2.de.hosts:
/etc/bind/bergische2.eu.hosts:

Er spaltet immer gleich auf:
- $0 = der ganze Original-Ausdruck (kenne ich so auch von PHP)
- $1 = Siehe oben
- $2 = 2008070100

Aber die Lösung ist da, also ist das nicht so schlimm.

Danke und Gruß
Claus
 
Back
Top