Forum: PC-Programmierung Zeichenkette mit regulärem Ausdruck ersetzen


von Walter T. (nicolas)


Lesenswert?

Hallo zusammen,
ich schreibe gerade an einem kleinen Matlab-Script, das (unter anderem) 
eine Zeichenkette vom Typ:

IMG_xxxx.JPG oder IMG_xxxxx.JPG

in eine Zeichenkette vom Typ

IMG_Axxxx.JPG

ersetzen soll, d.h. es soll aus einer vier- oder fünfstelligen Ziffer 
immer eine fünfstellige Ziffer erzeugt werden, indem eine Null 
vorangestellt wird, und anschließend soll ein Buchstabe "A" 
vorangestellt werden.

Matlab kennt den Befehl "regexprep", allerdings bekomme ich bei 
Regulären Ausdrücken regelmäßig einen Knoten im Kopf.

Gibt es hier einen Regulärer-Ausdruck-Experten, der soetwas hingebastelt 
bekommt (und am besten noch erklärt wie) ?

Natürlich könnte ich auch eben eine Funktion schreiben, die genau diese 
Ersetzung vollzieht. Um genau zu sein gibt es die schon (zum 
Gegentesten).

Viele Grüße
W.T.

von Vlad T. (vlad_tepesch)


Lesenswert?

Ich hab matlabs jetzt nicht gerade als Textmanipulationswekzeug in 
erinnerung ;)


Ich würde das zweistufig machen, erst alle auf 5 Ziffern erweitern und 
im nächsten schritt das A voranstellen
aber der regex sollte in etwa so aussehen:

regexprep(str, "IMG_(\\d\\d\\d\\d)\\.JPG", "IMG_0$1.JPG")
und
regexprep(str, "IMG_(\\d\\d\\d\\d\\d)\\.JPG", "IMG_A$1.JPG")

edit:
regexprep(post, "\\", "\\\\")

: Bearbeitet durch User
von Carl D. (jcw2)


Lesenswert?

Wer dein EDIT versteht, der hätte keine Hilfe gebraucht ;-)

von c-hater (Gast)


Lesenswert?

Walter T. schrieb:

> Matlab kennt den Befehl "regexprep", allerdings bekomme ich bei
> Regulären Ausdrücken regelmäßig einen Knoten im Kopf.

Dann entferne diesen Knoten. Ist ja schließlich keine Rekententechnik, 
sondern reine Fleiß-/Lern- Arbeit.

Hatte ich es schon erwähnt? Ich hasse Faule und Dumme, ganz besonders 
aber Dumme, die nur deshalb dumm sind, weil sie faul sind...

von Walter T. (nicolas)


Lesenswert?

Hallo zusammen,

Vlad T. schrieb:
> Ich hab matlabs jetzt nicht gerade als Textmanipulationswekzeug in
> erinnerung ;)

dafür ist es eigentlich ganz gut geeignet - zumindest dann, wenn alle 
Kollegen Matlab schon installiert haben und Python erst nachinstalliert 
werden müßte.


c-hater schrieb:
> Hatte ich es schon erwähnt? Ich hasse Faule und Dumme, ganz besonders
> aber Dumme, die nur deshalb dumm sind, weil sie faul sind...

Ich verstehe:
"Ich kenne mich mit Regulären Ausdrücken (und denen zur Ersetzung, die 
sich ein wenig von den anderen unterscheiden) aus. Und es gibt eine 
super Quelle, mit der man die gut lernen kann. Wer das nicht schafft, 
Reguläre Ausdrücke mit dieser Quelle zu lernen, ist ein Dummkopf. Ich 
verrate Dir aber die Quelle nicht, denn ich nenne lieber andere Leute 
'Dummkopf' als zu riskieren, daß sie schlauer werden."

oder:
"Ich habe zwar keine Ahnung von Regulären Ausdrücken (und denen zur 
Ersetzung), aber jede Menge schlechte Laune. In solchen Fällen schreibe 
ich gern zu Dingen, von denen ich keine Ahnung habe."

Welche der beiden Deutungen ist richtig?


Vlad T. schrieb:
> regexprep(str, "IMG_(\\d\\d\\d\\d)\\.JPG", "IMG_0$1.JPG")
> und
> regexprep(str, "IMG_(\\d\\d\\d\\d\\d)\\.JPG", "IMG_A$1.JPG")
>
> edit:
> regexprep(post, "\\", "\\\\")

Ich habe Deinen Code mal angewendet (in einer for-Schleife):
1
    srcname
2
    dstname2 = regexprep(srcname,  'IMG_(\d\d\d\d)\.JPG', 'IMG_0$1.JPG')
3
    dstname3 = regexprep(dstname2, 'IMG_(\d\d\d\d\d)\.JPG', 'IMG_A$1.JPG')
4
    
5
    
6
    K{i,1} = srcname;
7
    K{i,2} = dstname2;
8
    K{i,3} = dstname3;

Und es funktioniert prima:
1
K = 
2
3
    'IMG_0024.CR2'    'IMG_0024.CR2'     'IMG_0024.CR2'  
4
    'IMG_0738.CR2'    'IMG_0738.CR2'     'IMG_0738.CR2'  
5
    'IMG_0738.JPG'    'IMG_00738.JPG'    'IMG_A00738.JPG'
6
    'IMG_0740.CR2'    'IMG_0740.CR2'     'IMG_0740.CR2'  
7
    'IMG_0740.JPG'    'IMG_00740.JPG'    'IMG_A00740.JPG'
8
    'IMG_0750.CR2'    'IMG_0750.CR2'     'IMG_0750.CR2'  
9
    'IMG_0750.JPG'    'IMG_00750.JPG'    'IMG_A00750.JPG'
10
    'IMG_0761.CR2'    'IMG_0761.CR2'     'IMG_0761.CR2'  
11
    ...
(Daß das bei Dateinamen mit der Endung ".CR2" nicht funktioniert ist ja 
OK - ich habe die Anforderung vergessen zu nennen).

Carl D. schrieb:
> Wer dein EDIT versteht, der hätte keine Hilfe gebraucht ;-)

Das stimmt leider. Ich hätte das EDIT so geschrieben:
regexprep(post, "\\\\", "\\")
aber in Regulären Ausdrücken bin ich ja alles andere als fit.

Danke für die Hilfe!

von Boris O. (bohnsorg) Benutzerseite


Lesenswert?

Wenn du die Dateiendung egalisieren willst, einfach \.JPG gegen \.\w{3} 
oder \.(JPG|CR2) ersetzen. Der Punkt muss mit Backslash markiert werden. 
Weiters muss es in 2 Stufen gemacht werden, weil reguläre Ausdrücke 
nicht zurückschauen können. Es gibt aber Erweiterungen, die das können, 
d.h. ein wenn/dann auf \0 geht dann doch. Dafür kenne ich aber MatLab 
Regex zu wenig.

von Walter T. (nicolas)


Lesenswert?

Boris O. schrieb:
> Dafür kenne ich aber MatLab
> Regex zu wenig.

Das paßt schon so. Mit
1
dstname = regexprep(srcname,  'IMG_(\d{4})\.(JPG|CR2)', 'IMG_A0$1.$2')
ist aus der Gesamtaufgabe ein relativ portabler Einzeiler geworden - 
genau das, was ich gesucht habe.

Danke!

: Bearbeitet durch User
von Norbert (Gast)


Lesenswert?

Walter T. schrieb:
> Das paßt schon so. Mitdstname = regexprep(srcname,
> 'IMG_(\d{4})\.(JPG|CR2)', 'IMG_A0$1.$2')
> ist aus der Gesamtaufgabe ein relativ portabler Einzeiler geworden -
> genau das, was ich gesucht habe.

Ich mag ja falsch liegen, aber das sieht für mich so aus als wenn bei 
einer fünfstelligen Zahl im 'srcname' hier kein Treffer gelandet wird.

von Tom (Gast)


Lesenswert?

Walter T. schrieb:
> dafür ist es eigentlich ganz gut geeignet - zumindest dann, wenn alle
> Kollegen Matlab schon installiert haben und Python erst nachinstalliert
> werden müßte.

Ab ein paar 100MB zu bearbeitendem Text hat man die Zeit für die 
Python-Installation IME herausgeholt...

von Vlad T. (vlad_tepesch)


Lesenswert?

Walter T. schrieb:
> Das stimmt leider. Ich hätte das EDIT so geschrieben:
> regexprep(post, "\\\\", "\\")

das sollte ja heißen, dass ich die striche verdoppelt habe und nicht, 
dass sie entfernt werden müssen.
Bei mir hat octave wegen dem \d rumgemeckert, als ich ihm den String
"IMG_(\d\d\d\d)\.JPG" vorgeworfen habe, weil der Kommandoparser 
natürlich versucht einen String mit \d-Zeichen zu generieren, \d aber 
keine gültige Escape-Sequenz ist. will man ein normales \ im String 
haben (der ja der Input für die Regex-Engine ist), muss man wie bei C 
auch dieses Escapen.

Ihr habt aber Single-Qutes verwendet, wo das nicht nötig zu sein 
scheint, wessen ich mir aber nicht bewusst war.

von Walter T. (nicolas)


Lesenswert?

Vlad T. schrieb:
> Ihr habt aber Single-Qutes verwendet, wo das nicht nötig zu sein
> scheint, wessen ich mir aber nicht bewusst war.

Das ist interessant... dieser Unterschied zwischen double-quote-Strings 
und Single-quotes strings war mir noch nie bewußt.

Unter Matlab funktioniert nur:
1
srcname = 'IMG_1234.JPG'
2
dstname = regexprep(srcname,  'IMG_(\d{4})\.(JPG|CR2)', 'IMG_A0$1.$2')

Unter Octave gehen:
1
srcname = 'IMG_1234.JPG'
2
dstname = regexprep(srcname,  'IMG_(\d{4})\.(JPG|CR2)', 'IMG_A0$1.$2')
3
dstname = IMG_A01234.JPG
4
5
% wirklich die Mischung aus \\d und \.
6
dstname = regexprep(srcname,  "IMG_(\\d{4})\.(JPG|CR2)", 'IMG_A0$1.$2')
7
dstname = IMG_A01234.JPG
nicht gehen:
1
dstname = regexprep(srcname,  "IMG_(\\\\d{4})\\\\.(JPG|CR2)",'IMG_A0$1.$2')
2
dstname = IMG_1234.JPG

Ich verstehe noch nicht, was die vier Schrägstriche bewirken sollen.

Norbert schrieb:
> Ich mag ja falsch liegen, aber das sieht für mich so aus als wenn bei
> einer fünfstelligen Zahl im 'srcname' hier kein Treffer gelandet wird.

Da hast Du Recht. Das ist eine Anforderung, die ich mittlerweile 
fallengelassen habe. Das wird vorher herausgeprüft.

Tom schrieb:
> Ab ein paar 100MB zu bearbeitendem Text hat man die Zeit für die
> Python-Installation IME herausgeholt...

Das bezweifele ich - aber da kannst Du gern einen Wettbewerb ausrufen.

: Bearbeitet durch User
von Vlad T. (vlad_tepesch)


Lesenswert?

Walter T. schrieb:
> % wirklich die Mischung aus \\d und \.
> dstname = regexprep(srcname,  "IMG_(\\d{4})\.(JPG|CR2)", 'IMG_A0$1.$2')

das geht bei mir nicht.
Wenn ich octace einen String mit \. vorwerfe kommt:
1
octave.exe:2> S = "IMG_(\\d{4})\.(JPG|CR2)"
2
warning: unrecognized escape sequence `\.' -- converting to `.'
3
S = IMG_(\d{4}).(JPG|CR2)
4
5
octave.exe:3> S2 = "IMG_(\\d{4})\\.(JPG|CR2)"
6
S2 = IMG_(\d{4})\.(JPG|CR2)

bei regulären ausdrücken besteht ein deutlicher Unterschied zwischen;

IMG_(\d{4}).(JPG|CR2)
und
IMG_(\d{4})\.(JPG|CR2)

von Heinz B. (Firma: Privat) (hbrill)


Lesenswert?

Soll die Zahl inclusive zus. 0 5 Stellen lang sein
oder aber bei einer 5stelligen dann eben eine
6stellige ?
Andernfalls müßte man bei einer 5stelligen
die erste Ziffer löschen.
Da die Dateien der 8.3 -Notation folgen (also
immer eine 3stellige Dateiendung) wäre das vielleicht
vernachlässigbar.

Habs hier mal mit XProfan gemacht :

Declare String s[], n
Set("RegEx", 1)

s[] = "IMG_1234.JPG", "IMG_1234.CR2", "IMG_12345.JPG", "IMG_12345.CR2", 
"IMG_0024.CR2", "IMG_0738.CR2",\
      "IMG_0738.JPG", "IMG_0740.CR2", "IMG_0740.JPG",  "IMG_0750.CR2", 
"IMG_0750.JPG", "IMG_0761.CR2"
Cls

WhileLoop 0, 11
   n = Match$("[0-9]{4,5}", s[&LOOP])
   If LEN(n) = 4
      n = INS$("A0", n, 1)
      s[&LOOP] = Translate$(s[&LOOP], $Match, n)
   ElseIf LEN(n) = 5
      n = DEl$(n, 1, 1) ' bei 5stellig bei 6stellig -> weglassen
      n = INS$("A0", n, 1)
      s[&LOOP] = Translate$(s[&LOOP], $Match, n)
   EndIf
EndWhile

WhileLoop 0, 11
  Print s[&LOOP]
EndWhile

/* Ausgabe sieht so aus :
IMG_A01234.JPG
IMG_A01234.CR2
IMG_A02345.JPG
IMG_A02345.CR2
IMG_A00024.CR2
IMG_A00738.CR2
IMG_A00738.JPG
IMG_A00740.CR2
IMG_A00740.JPG
IMG_A00750.CR2
IMG_A00750.JPG
IMG_A00761.CR2
*/

WaitKey
Set("RegEx", 0)
End

Wie ich sehe, hat Matlab ja auch eine Ersetzen-Funktion
bei den reg. Ausdrücken. Da könnte das dann ähnlich
wie in XProfan funktionieren und mein Code als Anregung
dienen.

von Walter T. (nicolas)


Lesenswert?

Hallo Heinz,

für mich ist das ursprüngliche Problem gelöst und erledigt und das 
kleine Script hat gestern mit der Lösung von Dracula ein paar tausend 
Fotos erfolgreich konsistent umbenannt.

Jetzt interessiert mich eigentlich nur noch die Schreibweise mit den 
zahlreichen "\\\\", also warum die Backslashes so oft trunkiert werden, 
als wäre irgendwie dem "regexprep" noch intern ein "printf" oder so 
vorangestellt.

von Hans (Gast)


Lesenswert?

Walter T. schrieb:
> Jetzt interessiert mich eigentlich nur noch die Schreibweise mit den
> zahlreichen "\\\\", also warum die Backslashes so oft trunkiert werden,
> als wäre irgendwie dem "regexprep" noch intern ein "printf" oder so
> vorangestellt.

Der Kommentar sollte bedeuten, dass er beim Editieren seines Posts einen 
einzelnen Backslash (\) durch zwei Backslashes (\\) ersetzt hat.

Wenn das ein Script machen soll, sieht das so aus:
regexprep(post, '\', '\\')

Wenn man den gleichen Aufruf in Double-Quotes schreibt, muss man jeden 
Backslash escapen, damit er nicht als Steuerzeichen innerhalb des 
Strings interpretiert wird:
regexprep(post, "\\", "\\\\")

von Walter T. (nicolas)


Lesenswert?

OK, also der Edit-Text war eine Vollzugsmeldung, keine Ergänzung. Das 
erklärt einiges.

Aber warum müssen  Zeichen in "doulble quotes" anders "escapiert" werden 
als in "single quotes" ?

: Bearbeitet durch User
von Hans (Gast)


Lesenswert?


von Walter T. (nicolas)


Lesenswert?

Achso, einfach mal wieder einer der Fälle, wo diejenigen, die sich ein 
besseres Matlab wünschen, mit mit der Zunge schnalzen und diejenigen, 
die sich ein kostenloses Matlab wünschen mit den Augen rollen.

von Vlad T. (vlad_tepesch)


Lesenswert?

Walter T. schrieb:
> Achso, einfach mal wieder einer der Fälle, wo diejenigen, die sich ein
> besseres Matlab wünschen, mit mit der Zunge schnalzen und diejenigen,
> die sich ein kostenloses Matlab wünschen mit den Augen rollen.

tatsache - matlab kennt keine double quotes.
wie bekommt man denn ein tab (oder andere non printables) in einen 
Matlab string?

von Walter T. (nicolas)


Lesenswert?

Als Unicode. Also notfalls per "sprintf" in einen String.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.