• Willkommen im Linux Club - dem deutschsprachigen Supportforum für GNU/Linux. Registriere dich kostenlos, um alle Inhalte zu sehen und Fragen zu stellen.

[gelöst] Reguläre Ausdrücke

Hallo zusammen,

ich habe folgerndes Problem:
Wenn ich mit:
Code:
grep '^[A-Z]' datei
alle Zeilen sehen will, die mit einem großen Buchstaben beginnen sehen will, bekomme ich immer fast alle Zeilen ausgegeben. Als Beispiel habe ich die passwd kopiert und bei einigen Benutzern am Anfang einen Buchstaben groß geschrieben. Es kommen aber erheblich mehr Zeilen als die mit einem Großbuchstaben am Anfang zur Ausgabe.

Mache ich das gleiche unter OS-X auf der bash funktioniert das so wie ich es erwartet habe.

Ein:
Code:
grep '^A' datei
funktioniert ohne Probleme ich bekomme alle Zeilen die mit einem großen "A" beginnen nur die Bereichsangabe beim regulären Ausdruck scheint nicht zu passen.

Wo liegt denn da der Hund begraben?

30 min. Später mal ein Nachtrag:

mit:
Code:
grep '^[[:upper:]]' datei
funktioniert es. Aber warum nicht so wie oben :-(
 
A

Anonymous

Gast
Schau mal ob es das hier ist. ;)
Da stehen solche Sätze wie
die Erklärung das das nur auf die Suchreihenfolge zurückzuführen ist, hat somit aber weitreichende Auswirkungen auf die Angabe von Bereichen.
der Bereich [a-z] bedeutet für die bash somit
aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYz
und der Bereich [A-Z] bedeutet somit
AbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ

robi
 
Hi Robi,

es liegt nicht an der bash selber. Auf allen Shells (ksh, zsh) habe ich das selbe Ergebnis. Auf OS-X habe ich die selben Einstellungen bei "locale" wie unter Linux und es läuft. Mit setzen der Variablen läuft es aber auch nicht ;-)
 
A

Anonymous

Gast
ich hab jetzt hier nur eine etwas in die Jahre gekommene VM mit OpenSuse 11.irgendwas und die verhält sich genau wie erwartet mit
LANG=en_US.UTF-8 wird mit grep fast alles gefunden und mit LANG=C arbeitet sie normal.
Code:
LINUX: # grep '^[A-Z]' test
Aabcde
Babcde
cabcde
dabcde
eabcde
fabcde
gabcde
habcde
Iabcde
Jabcde
Kabcde
Labcde
Mabcde
nabcde
oabcde
pabcde
qabcde
Rabcde
Sabcde
Tabcde
Uabcde
xabcde
yabcde
zabcde
Zabcde
LINUX: # echo $LANG
en_US.UTF-8
LINUX: # LANG=C
LINUX: # grep '^[A-Z]' test
Aabcde
Babcde
Iabcde
Jabcde
Kabcde
Labcde
Mabcde
Rabcde
Sabcde
Tabcde
Uabcde
Zabcde
LINUX: #
 
Hallo stka,

stka schrieb:
Code:
grep '^[A-Z]' datei
alle Zeilen sehen will, die mit einem großen Buchstaben beginnen sehen will, bekomme ich immer fast alle Zeilen ausgegeben. Als Beispiel habe ich die passwd kopiert und bei einigen Benutzern am Anfang einen Buchstaben groß geschrieben. Es kommen aber erheblich mehr Zeilen als die mit einem Großbuchstaben am Anfang zur Ausgabe.
Hier mit grep (GNU grep) 2.13 geht das wie gewünscht.

Lieben Gruß aus Hessen
 
grep (GNU grep) 2.9
GNU bash, Version 4.2.10(1)-release (x86_64-suse-linux-gnu)

Mit
Code:
keine Angabe (= de_AT.UTF-8)
LANG=C
LANG=en-UK
LANG=en_US.utf8
LANG=POSIX
LANG=yi_US.utf8
LANG=zh_HK
funktioniert es bei mir wie gewünscht, der 8. Versuch mit
Code:
LANG=hr_HR
brachte dann alle Zeilen, die mit einem Klein- oder Großbuchstaben beginnen (Zeilen, die mit einem Leerzeichen, einem Sonderzeichen oder einer Ziffer beginnen, waren nicht dabei). Warum das so ist, ist für mich aber ein spanisches Dorf.
 
A

Anonymous

Gast
Ob das an speziellen Versionen von Programmen liegt glaube ich weniger. letztlich ist das irgendwo in GLIBC wo alle Programme und Tools darauf zugreifen.
Konfiguriert ist es wohl mit den Dateien die "find /usr/lib -name "LC_COLLATE" " findet, ob daran viel geändert wird, ich glaube nicht.
Es spielen aber neben der Variable LANG vor allem noch die Variablen LC_COLLATE und LC_ALL und ob sie existieren und sie exportiert sind eine wesentliche Rolle dabei. Wie und wo jetzt die Variablen gesetzt, besetzt und ausgewertet werden, könnte aber eventuell in einzelnen Distributionen durchaus unterschiedlich sein und auch zB abhängig von der Anmeldemethode des Users oÄ sein. Die Sortierreihenfolge ist nun mal in den einzelnen Sprachen und Zeichensätzen unterschiedlich definiert, man sollte solchen Problemen in größeren Scripten (welche auch noch auf anderen Rechnern laufen sollen) möglichst weit aus dem Weg gehen, das gibt Chaos ohne Ende und niemand erkennt auf Anhieb wo der Fehler dann in so einem Script liegen könnten, da so ein Script dann scheinbar funktioniert oder auch nicht wie es ihm gerade gefällt.

Allgemein findet man überall entsprechende Warnungen wenn es ums sortieren geht. wie hier zB in der Manpage von sort
*** WARNING *** The locale specified by the environment affects sort order. Set
LC_ALL=C to get the traditional sort order that uses native byte values.

robi
 
Also wenn ich "LANG=C" setze dann wird richtig sortiert und gelöscht. Ist ja eine ganz böse Sache so. Na ja jetzt weiß ich es. Ach so auf der ksh geht es auch so.
Danke an alle die geholfen haben.
 
"man grep" sagt ja auch ein bißchen was zu $LANG usw.. Ich hab' das ehrlich gesagt nie so recht kapiert. Noch weniger diese Option:
-P, --perl-regexp Interpret PATTERN as a Perl regular expression
Vielleicht hilft so eine Perl-Regex in grep ja bei dem Problem. Keine Ahnung, wo der Unterschied zu grep-Regexes sein soll.
Ich nehm' jedenfalls immer die Perl-Regex, da ich mit den Regexes in Perl besser vertraut bin. Kann mir eigentlich nicht vorstellen, daß Regexes in Perl von $LANG abhängig sein sollen.
Seltsames Problem ...
 
A

Anonymous

Gast
abgdf schrieb:
Seltsames Problem ...
Ich kann mir sehr gut vorstellen, dass dieses Problem in Perl genauso auftritt, wenn man nicht aufpasst, eventuell ist es dort etwas besser abgesichert. (eventuell wird dort im Kopf irgendwo eine Kennwort eingefügt, zB "Posix" und damit ist in machfolgendem Script genau das gemacht, was die Umgebungsvariablen in der Bash auch machen. Aber das Problem ist gar nicht so seltsam, sondern logisch, man muss es sich nur veranschaulichen.

Stell euch ein Telefonbuch vor. Die Namen dort müssen sortiert sein, nur somit kann man dort überhaupt was finden. Dann sollen aber auch ein Firmenname "ABC Sonne" sich in der Nähe von der Firma "abc Sonnenschein" befinden und nicht 300 Seiten weiter hinten, und ein Name "Bassfeld" sollte nicht weit von einem Namen "Baßfeld" zu finden sein, ein Nachname "Übelmann" sollte sich in der Näche von Namen "Ubelmann" befinden und so weiter. Ist einem vielleicht bisher noch nie so richtig aufgefallen, aber das erwarten wir einfach so, und daran haben wir uns gewöhnt.
Das ist die deutsche Sortierreihenfolge und ist irgendwo definiert. Ein Rechner soll jetzt wenn wir deutsch eingestellt haben die Worte auch genauso sortieren.

Sortieren wir dann mit irgend einem Programm Wörter nach dieser Definition, dann erhalten wir eben ein Ergebnis in der Buchstabenreihenfolge "aAbBcCdD......"
Suchen wir in diesem Ergebnis jetzt von "A bis D" dann wird erst sortiert und dann alles was kleiner als "A" und größer als "D" ist wird aus dem Sortierergebnis weggeschnitten, dort ist dann aber natürlich "b" "c" "d" auch noch dazwischen und wohl genauso dazwischen einsortiert hätte sich das "Ä" und "ä" und in anderen Sprachen dann noch alles mögliche mit Strichen, Hacken und Dächern auf dem "A" und "c". Wenn wir wirklich nur A B C und D haben wollen, dann müssen wir die Suchanfrage anders (oder genauer oder eindeutiger) definieren, zB. suche "Großbuchstaben von A bis D" . oder suche "A oder B oder C oder D"

Wenn wir dauerhaft, zuverlässig und in allen Sprachen einheitlich nach "A bis Z" oder von "a bis z" suchen wollen und damit nur Großbuchstaben oder Kleinbuchstaben meinen und diakritische Zeichen dabei ganz außen vorlassen können, dann müssen wir dem Rechner sagen, er soll nicht Länderspezifisch sortieren, sondern nach einem einheitlichen System zB dem ASCII-Code.

Dieses Problem sollte sich so in allen Sortierprogrammen ergeben, die länderspezifisch sortieren können und nicht nur rein Nummerisch.

robi
 
Ich glaub' ich hab' das Problem immer noch nicht ganz verstanden (sorry):
robi schrieb:
der Bereich [A-Z] bedeutet somit
AbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ
Warum denn das???

Sollte "[A-Z]" nicht einfach "ABCDEFGHIJKLMNOPQRSTUVWXYZ" bedeuten?
Da sind doch auch gar keine Umlaute. Wieso hat das denn was mit den Ländereinstellungen zu tun?

Vielen Dank für weitere Auskunft. ;)
 
Die Bereiche werden auf Grund des Inhalts von /usr/lib/locale/*/LC_COLLATE festgelegt (die der Mensch nicht lesen kann und deren tatsächliche Anzahl durch viele hardlinks gar nicht so groß ist). Aber was haben sich die Datei- und Regel-Erfinder dabei gedacht? Und wo ist das dokumentiert?

Es mutet für mich seltsam an, wenn LC_COLLATE=en_US.utf8 Umlaut-Großbuchstaben bei [A-Z] auswählt (und alle Kleinbuchstaben für mich korrekt nicht auswählt), während LC_COLLATE=hr_HR.utf8 Klein- und Großbuchstaben samt Umlauten anzeigt (da müssen die Regeln wohl sehr kryptisch sein).

Das ist für mich eine jener Gelegenheiten, wo ich mir sage, daß ich nicht alles verstehen muß.
 
A

Anonymous

Gast
abgdf schrieb:
Ich glaub' ich hab' das Problem immer noch nicht ganz verstanden (sorry):
robi schrieb:
der Bereich [A-Z] bedeutet somit
AbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ
Warum denn das???

Sollte "[A-Z]" nicht einfach "ABCDEFGHIJKLMNOPQRSTUVWXYZ" bedeuten?
Da sind doch auch gar keine Umlaute. Wieso hat das denn was mit den Ländereinstellungen zu tun?

Vielen Dank für weitere Auskunft. ;)

Je nachdem was man für ein Lesematerial benutzt (entsprechend Zielgruppe, Qualität und Aktualität) gibt es prinzipiell 2 grundlegende Aussagen: hier mal 2 Beispiele
http://de.wikipedia.org/wiki/Regul%C3%A4rer_Ausdruck
Wikipedia schrieb:
Steht ein Bindestrich - zwischen zwei Zeichen in der Klassendefinition, zum Beispiel „[a-g]“, so ist es als Bis-Strich zu verstehen, d.h. als Beschreibung eines Zeichenintervalls oder Zeichenbereichs bezüglich der ASCII-Tabelle.
http://www.lrz.de/services/schulung/unterlagen/regul/#bracket
Schulungsunterlagen schrieb:
Welche Zeichen in einem Bereich liegen, der mit Bindestrich notiert wird, richtet sich nicht nach der Codierung (etwa im ASCII- oder ISO8859-1-Code), sondern nach der Sortierreihenfolge, die systemweit oder benutzerspezifisch nach den Gepflogenheiten einzelner Länder eingestellt sein kann. Es ist also nicht von vorneherein klar, ob etwa das scharfe ß im Bereich [a-z] enthalten ist oder nicht. Spezifiziert man explizit die "POSIX Locale" durch Setzen der Environment-Variablem LC_COLLATE auf den Wert POSIX, so liegen wenigstens die Zeichen des ASCII-Codes in der durch diesen Code spezifizierten Reihenfolge; über die übrigen Schriftzeichen schweigt sich die Norm allerdings aus.
Etwas klarer und deutlicher wo zumindestens ein Teil der Probleme herkommt http://en.wikipedia.org/wiki/Regular_expression#Unicode
diesen Satz sollte man sich schon mal merken:
Wikipedia:en schrieb:
In most respects it makes no difference what the character set is, but some issues do arise when extending regular expressions to support Unicode.
Wer will kann sich näher mit dem Thema beschäftigen, Unterlagen und Diskussionen darüber gibt es wohl zu tausenden im Netz.
Es ist in einigen Details bestimmt ein recht schwieriges Thema. Wo jetzt genau die Definitionen hinterlegt sind, keine Ahnung. So tief möchte ich mich gar nicht damit beschäftigen. Aber viel interessanter ist auch wer wie damit dann umgeht und wie es Umgesetzt ist. Hier gibt es zB. durchaus schon recht auffällige Differenzen im Verhalten in den einzelnen OpenSuse Versionen. Man muss auch nicht alles verstehen, aber man sollte die Klippen kennen, damit man sich von ihnen möglichst weit weg halten kann. ;)

robi
 
josef-wien schrieb:
Das ist für mich eine jener Gelegenheiten, wo ich mir sage, daß ich nicht alles verstehen muß.
Ich im Prinzip auch nicht. Aber es ist schon bitter, wenn eine Regex unerwartet so bös' nach hinten losgeht.
Code:
[A-Z] != [a-zA-Z]
sollte man denken.
 
ist einfach.

Jedweder RE ist abhängig von den eingestellten Sprachvariablen ($L*)
und von den verwendeten Codepunkttabellen. (UTF-x, Latin, usw.)
.Davon gibt es sehr viele.
Und passen all diese verschiedenen Einstellmöglichkeiten (die sind letztlich Legion) und die Ausgangsdaten nicht hundertprozentig zusammen, so können seltsame Dinge passieren.

Deshalb sollte man in RegExen -egal welcher Couleur- immer nur mit Zeichenklassen arbeiten.
Gib in deinem Konqueror folgende Adresse ein:
"info:/grep/Character Classes and Bracket Expressions"

Wenn du diese Charakterklassen verwendest, die die jeweilige Locale VOLL berücksichtigen,
so sind die Ergebnisse zuverlässiger. Und vor allem portabel.

Klappt es dann immer noch nicht, so suche in den Eingabedaten.
Meist ist dann dort ein "dicker Hund" begraben.
Kopiere -in deinem Falle hier- den Rest einer Vorgängerzeile bis nach dem nichterkannten Anfangsbuchstaben in eine extra Datei.
Und nimm dann den Befehl:
"cat NeueFehler | od -a"
Dann siehst du, ob da alles am Zeilenende der Vorgängerzeile stimmt.
Das dürfte wohl der häufigste Grund sein, warum ein
" grep '^[[:upper:]]' halligalli"
schiefgehen kann.
 
Oben