Bash 4.2 & 4.3 Regex-Unterschied

Vom einfachen Programm zum fertigen Debian-Paket, Fragen rund um Programmiersprachen, Scripting und Lizenzierung.
Antworten
bumer
Beiträge: 238
Registriert: 02.07.2014 12:29:15

Bash 4.2 & 4.3 Regex-Unterschied

Beitrag von bumer » 06.08.2015 14:54:09

Hallo,

ich möchte bei der Ausgabe von `ls -la` das "insgesamt XXX" und die Punkte (. ..) nicht anzeigen. Das hat bisher immer gut mit Debian 7 und Bash 4.2.37 funktioniert:

Code: Alles auswählen

ls -la | awk 'NF > 2 && $9 !~ /^(\.){1,2}$/ {print $0}'
Mit Debian 8 und Bash 4.3.30 geht das nicht mehr. Ich könnte natürlich auch folgendes schreiben:

Code: Alles auswählen

ls -la | awk 'NF > 2 && $9 !~ /^(\.)+$/ {print $0}'
# oder
ls -la | awk 'NF > 2 && $9 !~ /^(\.)(\.)$/ {print $0}'
Aber irgendwie wundert es mich schon wieso ich das {n,n}-Konstrukt nicht mehr nutzen kann. Auch \{n,n\} geht nicht mehr. Wurde dieser wichtige Regex aus Bash > 4.2 komplett entfernt?

Viele Grüße,
bumer

Benutzeravatar
CH777
Beiträge: 1466
Registriert: 27.05.2008 16:37:17

Re: Bash 4.2 & 4.3 Regex-Unterschied

Beitrag von CH777 » 06.08.2015 15:41:54

Ohne deine Frage beantworten zu können möchte ich trotzdem noch einen etwas einfacheren Ansatz für das von dir gewünschte Ergebnis vorstellen:

Code: Alles auswählen

ls -la | tail -n +4

bumer
Beiträge: 238
Registriert: 02.07.2014 12:29:15

Re: Bash 4.2 & 4.3 Regex-Unterschied

Beitrag von bumer » 06.08.2015 16:03:20

CH777 hat geschrieben:Ohne deine Frage beantworten zu können möchte ich trotzdem noch einen etwas einfacheren Ansatz für das von dir gewünschte Ergebnis vorstellen:

Code: Alles auswählen

ls -la | tail -n +4
Ja, oder auch:

Code: Alles auswählen

ls -la | sed '1,3d'
Ja, schlechtes Beispiel, aber es geht mir nur um das {n,n}-Konstrukt, da ich es öfter nutze.

uname
Beiträge: 12400
Registriert: 03.06.2008 09:33:02

Re: Bash 4.2 & 4.3 Regex-Unterschied

Beitrag von uname » 06.08.2015 16:04:57

Ich habe eine weit schlechtere Lösung anzubieten ;-)

Code: Alles auswählen

ls -la | tac | head -n -4 | tac 

Benutzeravatar
4A4B
Beiträge: 962
Registriert: 09.11.2011 11:19:55
Kontaktdaten:

Re: Bash 4.2 & 4.3 Regex-Unterschied

Beitrag von 4A4B » 06.08.2015 16:05:30

Mit Debian 8 und Bash 4.3.30 geht das nicht mehr.
Kann ich bestätigen - allerdings scheint es in Debian 9 (bash 4.3.39) wieder zu funktionieren. Sowohl auf Debian 8 als auch auf Debian 9 ist mawk 1.3.3-17 installiert

Benutzeravatar
Meillo
Moderator
Beiträge: 9235
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Re: Bash 4.2 & 4.3 Regex-Unterschied

Beitrag von Meillo » 06.08.2015 23:31:29

Stehe ich auf dem Schlauch, oder sehe ich es richtig, dass dies gar nichts mit der Bash zu tun hat, sondern ausschliesslich mit awk?

Also, schauen wir mal genauer hin: Awk wird bei Debian ueblicherweise durch GNU awk (gawk) oder durch mawk bereit gestellt. Die Manpage meines mawk sagt:
AWK uses extended regular expressions as with egrep(1). The regular
expression metacharacters, i.e., those with special meaning in regular
expressions are
^ $ . [ ] | ( ) * + ?
Da sind keine geschweiften Klammern und damit keine Interval-Angaben darunter.

Zur grundsaetzlichen Angabe bei awk: Bei Extended Regexps wie in awk werden escapte Zeichen (also wenn man einen Backslash davor macht) immer literal genommen. Die Sonderbedeutung gilt nur fuer die unescapte Form. (Das ist gegensaetzlich zu ed oder sed. Dort sind es aber auch Basic Regexps.)

So, dann ein Blick in POSIX: http://pubs.opengroup.org/onlinepubs/96 ... s/awk.html
Dort heisst es:
The awk utility shall make use of the extended regular expression notation [...]
Und unter EREs (http://pubs.opengroup.org/onlinepubs/96 ... #tag_09_04) steht:
When an ERE matching a single character or an ERE enclosed in parentheses is followed by an interval expression of the format "{m}", "{m,}", or "{m,n}", together with that interval expression it shall match what repeated consecutive occurrences of the ERE would match.
Laut POSIX sollte es also tun; mawk unterstuetzt es aber nicht. Wo liegt die Erklaerung?

Sie findet sich ebenfalls in POSIX, in der Seite von awk, wenn man nach ``interval'' sucht:
Regular expressions in awk have been extended somewhat from historical implementations to make them a pure superset of extended regular expressions, as defined by POSIX.1-2008 (see XBD Extended Regular Expressions). The main extensions are internationalization features and interval expressions.
Aufgrund der historischen Vorgeschichte hat mawk also keine Interval-Ausdruecke.

Es gibt nun drei Loesungsansaetze:

a) Installiere gawk, denn das unterstuetzt die, wie aus seiner Manpage zu entnehmen ist:
-r
--re-interval
Enable the use of interval expressions in regular
expression matching (see Regular Expressions,
below). Interval expressions were not tradition‐
ally available in the AWK language. The POSIX
standard added them, to make awk and egrep consis‐
tent with each other. They are enabled by
default, but this option remains for use with
--traditional.
b) Schreibe die Regexp um, z.B. in: /^\.\.?\/?$/ . Das hat zugleich den Vorteil, dass das auch funktioniert, wenn man `ls -laF' verwendet. (Btw: Wenn nur ein einziges Zeichen vor den Quantifier steht, dann brauchst du keine runden Klammern. Der Backslash-Escape gehoert zum Zeichen.)

c) Umgehe das Problem, z.B. mit:

Code: Alles auswählen

ls -lA | sed 1d
;-)
Use ed once in a while!

linuxCowboy
Beiträge: 287
Registriert: 05.02.2013 19:47:41

Re: Bash 4.2 & 4.3 Regex-Unterschied

Beitrag von linuxCowboy » 07.08.2015 13:33:29

auch:

Code: Alles auswählen

\ls -alF | sed -r '/^insgesamt|^total/d;/ \.\.?\/?$/d'
oder:

Code: Alles auswählen

\ls -Alp | sed '/^insgesamt\|^total/d'
-der_linux_cowboy --- Besser werden! ... f*** w$$

Antworten