[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: Für die sed / RegExp Experten



On 2004.01.26 11:15, Matthias Hentges wrote:
Hallo Liste!

Ich lese mittlerweile seit zwei Stunden diverse sed HowTo's aber ich
bin
wohl irgendwie zu dumm.

Folgendes Problem:

echo "2.6.2-rc1-mm3"| sed s/\-mm[1-99]//

bringt als Ergebnis "2.6.2-rc1".

Ich möchte aber genau das Gegenteil erhalten, nähmlich

"-mm3"

Also quasi eine invertierte RegExp, wobei aber nur der "-mm[1-99] Teil
des Strings bekannt ist.

Kenne mich mit sed-Syntax zwar nicht sonderlich aus, aber dafuer ein bisschen mit PERL, und reg-exes sind ja vom Prinzip her eh ueberall aehnlich. :-)

Zunaechst einmal a line recklessly stolen from Christoph Maurer <christoph-maurer@gmx.de>:

echo "2.6.2-rc1-mm3"| sed "s/.*\(-mm[0-9]\{1,\}\)/\1/"

Ich verlasse mich einfach mal drauf, dass die Syntax bei ihm stimmt. :-)

Könnte mir da jemand auf die Sprünge helfen? Möglichst mit Erklärung
:)
Ein Schubs in die richtige Richtung wäre schon genug.

Und jetzt auf meinem eigenen Mist gewachsen  der Schubs:

s/expression 1/expression 2/ sucht in einer Zeichenkette nach dem Ausdruck "expression 1" und ersetzt ihn mit "expression 2". Du hast zwar in "2.6.2-rc1-mm3" korrekt nach "\-mm[1-99]" gesucht, das dann aber mit nichts ersetzt.

Bei Christoph setzt sich der Suchstring so zusammen:
.* alles uninteressante, was vor dem gesuchten Teil des Ausdruckes steht
-mm[0-9]{1,}	der gesuchte Teil

Zwischen den eckigen Klammern ist ein Bereich erlaubter Zeichen angegeben. Damit wird aber immer nur nach _einem_ Zeichen gesucht. [1- 99] wuerde zB nicht funktionieren, um "23" zu finden, weil die 99 eben nicht fuer neunundneunzig steht, sondern einfach nur das Zeichen "9" doppelt in der Liste erlaubter Zeichen vorkommt. Effektiv laesst du also nur die Ziffern 1-9 zu, schliesst aber 0 aus. Ausserdem suchst du nur nach einer einzigen Ziffer. Statt "23" wuerde also nur "2" gefunden werden.

Christoph hat jetzt mit [0-9] den gueltigen Bereich um die 0 erweitert und mit ein bisschen Magic umgeben: Mit {1,} hat er festgelegt, dass das vorherstehende Zeichen mindestens einmal vorkommen muss. Mit {1,3} haette er auch sagen koennen, dass es mindestens einmal, jedoch nicht haeufiger als dreimal vorkommen darf; und mit {2} muesste es genau zweimal vorkommen. Den gesuchten Ausdruck hat er mit den runden Klammern als Teilausdruck festgelegt, auf den er spaeter Bezug nehmen kann. Das macht er im zweiten Teil mit \1:
	s/.*\(-mm[0-9]\{1,\}\)/\1/
Die \1 ist eine interne Variable, die einfach die Position des Ausdruckes in runden Klammern angibt. Der gesamte Ausdruck .*(-mm[0-9] {1,}) wird also durch den ersten eingeklammerten Teilausdruck ersetzt.

Weil das so kompliziert ausgedrueckt ist, nochmal ein anderes Beispiel.
Deinen Suchausdruck koennte man zB folgendermassen schreiben:
/\(.*\)\(-\)\(mm[0-9]\{1,\}\)/
Dann waere:
\1	\(.*\)
\2	\(-\)
\3	\(mm[0-9]\{1,\}\)

Mit s/\(.*\)\(-\)\(mm[0-9]\{1,\}\)/\3\2\1/ koenntest du dann aus "2.6.2-rc1-mm3" "mm3-2.6.2-rc1" machen...

Die manpage von SED war nicht wirklich erleuchtend....

Ich hoffe, etwas hilfreicher sein zu koennen. :-)


TIA
--

Matthias Hentges
Cologne / Germany

Schoenen Gruss,

Andreas



Reply to: