it-swarm.com.de

wie geben Sie nicht erfassende Gruppen in sed an?

ist es möglich, nicht erfassende Gruppen in sed anzugeben?

wenn das so ist, wie?

30
barlop

Die Antwort lautet: Wenn man schreibt, kann man das nicht - Sed unterstützt es nicht. Sed unterstützt BRE und ERE, jedoch nicht PCRE. 

(Hinweis: Eine Antwort weist darauf hin, dass BRE auch als POSIX sed bekannt ist und ERE eine Erweiterung von GNU über sed -r ist. Der Punkt bleibt, dass PCRE nicht von sed unterstützt wird.)

Perl funktioniert für Windows oder Linux

beispiele hier

https://superuser.com/questions/416419/Perl-zur-matching-mit-regelmäßigenAusdrücken-in-terminal

z.B. dies von Cygwin in Windows

$ echo -e 'abcd' | Perl -0777 -pe 's/(a)(?:b)(c)(d)/\1/s'
a

$ echo -e 'abcd' | Perl -0777 -pe 's/(a)(?:b)(c)(d)/\2/s'
c

Es gibt zwar ein Programm für Windows, das in der Befehlszeile suchen und ersetzen kann und PCRE unterstützt. Es heißt rxrepl. Es ist natürlich nicht sed, aber es sucht und ersetzt mit PCRE-Unterstützung.

C:\blah\rxrepl>echo abc | rxrepl -s "(a)(b)(c)" -r "\1"
a

C:\blah\rxrepl>echo abc | rxrepl -s "(a)(b)(c)" -r "\3"
c

C:\blah\rxrepl>echo abc | rxrepl -s "(a)(b)(?:c)" -r "\3"
Invalid match group requested.

C:\blah\rxrepl>echo abc | rxrepl -s "(a)(?:b)(c)" -r "\2"
c

C:\blah\rxrepl>

Der Autor (nicht ich) erwähnte sein Programm in einer Antwort hier https://superuser.com/questions/339118/regex-replace-from-command-line

Es hat eine wirklich gute Syntax.

Standardmäßig würde Perl oder fast jede andere Programmiersprache verwendet werden. 

8
barlop

Klammern können zum Gruppieren von Alternativen verwendet werden. Zum Beispiel:

sed 's/a\(bc\|de\)f/X/'

sagt, um "abcf" oder "adef" durch "X" zu ersetzen, aber die Klammern auch capture. In sed gibt es keine Möglichkeit, eine solche Gruppierung durchzuführen, ohne auch zu erfassen. Wenn Sie über einen komplexen Regex verfügen, der sowohl die alternative Gruppierung und Capturing durchführt, müssen Sie bei der Auswahl der richtigen Capture-Gruppe lediglich vorsichtig sein.

Vielleicht könnten Sie mehr darüber sagen, was Sie erreichen wollen (was Sie für nicht erfassende Gruppen benötigen) und warum Sie Erfassungsgruppen vermeiden möchten.

Bearbeiten:

Es gibt einen Typ von nicht erfassenden Klammern ((?:pattern)), die Bestandteil von Perl-kompatiblen regulären Ausdrücken (PCRE) sind. Sie werden in sed nicht unterstützt (bei Verwendung von grep -P).

27

Ich gehe davon aus, dass Sie von der Backrefence-Syntax sprechen, die Klammern ( ) und keine Klammern [ ] sind.

Standardmäßig interpretiert sed( ) wörtlich und versucht nicht, aus ihnen einen Backrefence zu machen. Sie müssen sie entgehen lassen, um sie wie \( \) zu spezifizieren. Nur wenn Sie die Option GNU sed -r verwenden, wird die Umkehrung rückgängig gemacht. Mit sed -r erzeugt ungeprüftes ( ) Rückschritte, und \( \) wird als Literal behandelt. Beispiele folgen:

POSIX sed

$ echo "foo(###)bar" | sed 's/foo(.*)bar/@@@@/'
@@@@

$ echo "foo(###)bar" | sed 's/foo(.*)bar/\1/'
sed: -e expression #1, char 16: invalid reference \1 on `s' command's RHS
-bash: echo: write error: Broken pipe

$ echo "foo(###)bar" | sed 's/foo\(.*\)bar/\1/'
(###)

GNU sed -r

$ echo "foo(###)bar" | sed -r 's/foo(.*)bar/@@@@/'
@@@@

$ echo "foo(###)bar" | sed -r 's/foo(.*)bar/\1/'
(###)

$ echo "foo(###)bar" | sed -r 's/foo\(.*\)bar/\1/'
sed: -e expression #1, char 18: invalid reference \1 on `s' command's RHS
-bash: echo: write error: Broken pipe

Aktualisieren

Aus den Kommentaren: 

Nur für Gruppen, die keine Klammern enthalten, ( ), so dass Sie Intervalle {n,m} verwenden können, ohne eine Rückwärtsreferenz \1 zu erstellen, existieren nicht. Erstens sind die Intervalle nicht von POSIX sed getrennt, Sie müssen die Erweiterung GNU -r verwenden, um sie zu aktivieren. Sobald Sie -r aktivieren, werden auch alle Gruppierungsklammern für die Verwendung von Rückverweisen erfasst. Beispiele:

$ echo "123.456.789" | sed -r 's/([0-9]{3}\.){2}/###/'
###789

$ echo "123.456.789" | sed -r 's/([0-9]{3}\.){2}/###\1/'
###456.789
3
SiegeX

Wie gesagt, es ist nicht möglich, nicht-einfangende Gruppen in sed zu haben. Es könnte offensichtlich sein, aber nicht einfangende Gruppen sind keine Notwendigkeit. Man kann einfach die gewünschten Erfassungs-Einsen verwenden und die Nicht-Gewünschten ignorieren, als ob sie nicht erfassen würden. Als Referenz werden verschachtelte Erfassungsgruppen mit der Positionsreihenfolge von "(") nummeriert.

Z.B., 

echo "Apple and bananas and monkeys" | sed -r "s/((Apple|banana)s?)/\1x/g"

applex und Banane s x und Affen (Anmerkung: "s" in Bananen, erste größere Gruppe)

vs

echo "Apple and bananas and monkeys" | sed -r "s/((Apple|banana)s?)/\2x/g"

applex und Bananax und Affen (Anmerkung: kein "s" in Bananen, zweite kleinere Gruppe)

0
Hector Llorens