ubuntuusers.de

replace - Reguläre Ausdrücke Perl - 5 Ziffern gefolgt von Punkt

Status: Gelöst | Ubuntu-Version: Ubuntu 14.04 (Trusty Tahr)
Antworten |

bongobong

Avatar von bongobong

Anmeldungsdatum:
12. Dezember 2008

Beiträge: 1820

Wohnort: Hamburg

Hallo,

ich habe ein paar Bilddateien umbenannt. Dabei ist mir ein Fehler passiert den ich nun gerne korrigieren möchte. Ich bekomme das alleine jedoch nicht richtig hin.

Ich habe folgende Bildnamen A-12345.jpg und 0-12341.jpg. Immer wenn es in einem Dateinamen fünf aufeinanderfolgende Zahlen vor denen ein Bindestrich und davor wieder eine Zahl ist gibt, soll zwischen dem letzten und vorletzten Zeichen ein Unterstrich hinzugefügt werden:

A-12345.jpg → A-12345.jpg A-12341.jpg → A-1234_1.jpg

Folgendes habe ich bereits herausgefunden: \d steht für Zahlen, also benötige ich dies fünf mal: \d\d\d\d\d Das Zeichen - kann direkt angegeben werden. Das Zeichen . muss demaskiert werden mit \. da . sonst für alles steht.

Also versuchte ich mal

1
2
rename 's/\d-\d\d\d\d\d\./\d-\d\d\d\d_\d\./g' *
→ Unrecognized escape \d passed through at (eval 1) line 1.

Die gewünschten Dateinamen werden nun zwar bearbeitet, jedoch erhalte ich A-12341.jpg → d-dddd_d.jpg und eine Warnung.

Kann mir hier jemand weiterhelfen?

Danke

edit:

  1. Man kann scheinbar auch gruppieren mit \d{5} statt \d\d\d\d\d

  2. Wie kann man bei regex ursprüngliche Zeichen behalten?

misterunknown Team-Icon

Ehemalige
Avatar von misterunknown

Anmeldungsdatum:
28. Oktober 2009

Beiträge: 4403

Wohnort: Sachsen

bongobong schrieb:

Die gewünschten Dateinamen werden nun zwar bearbeitet, jedoch erhalte ich A-12341.jpg → d-dddd_d.jpg und eine Warnung.

Dafür brauchst du Backreferences

Kann mir hier jemand weiterhelfen?

Ungetestet:

1
rename 's#\(\d-\d{4}\)\([0-9]\)\.#\1_\2#' *

Heißt: Alles, was zwischen \( und \) steht, merkt sich die Engine. Gesucht wird nach einer Ziffer, gefolgt von einem Stich, gefolgt von 4 Ziffern. Das ist die erste Gruppe, deren Ergebnisse gespeichert werden. Dann wird geprüft, ob noch eine fünfte Ziffer existiert, gefolgt von einem Punkt. Die fünfte Ziffer wird auch gemerkt.

Ersetzt wird das Ganze durch die erste gemerkte Zeichenkette (Ziffer Strich 4 weitere Ziffern) dann ein Unterstich, und dann die zweite gemerkte Zeichenkette (einzelne Ziffer).

track

Avatar von track

Anmeldungsdatum:
26. Juni 2008

Beiträge: 7174

Wohnort: Wolfen (S-A)

Das ganze geht noch eleganter mit Hilfe eines Lookbehind- Ausdrucks, zusätzlich zur Back Reference:

track@track:~$ echo -e 'A-12345.jpg\n0-12341.jpg'  |  perl -pe 's/(?<=\d-\d{4})(\d)\./_\1./'
A-12345.jpg
0-1234_1.jpg 

... p.s.: es geht auch ohne Back Reference, wenn man beides, Lookbehind + Lookahead verwendet:

track@track:~$ echo -e 'A-12345.jpg\n0-12341.jpg'  |  perl -pe 's/(?<=\d-\d{4})(?=\d\.)/_/'
A-12345.jpg
0-1234_1.jpg 

LG,

track

bongobong

(Themenstarter)
Avatar von bongobong

Anmeldungsdatum:
12. Dezember 2008

Beiträge: 1820

Wohnort: Hamburg

misterunknown schrieb:

Ungetestet:

1
rename 's#\(\d-\d{4}\)\([0-9]\)\.#\1_\2#' *

Heißt: Alles, was zwischen \( und \) steht, merkt sich die Engine. Gesucht wird nach einer Ziffer, gefolgt von einem Stich, gefolgt von 4 Ziffern. Das ist die erste Gruppe, deren Ergebnisse gespeichert werden. Dann wird geprüft, ob noch eine fünfte Ziffer existiert, gefolgt von einem Punkt. Die fünfte Ziffer wird auch gemerkt.

Ersetzt wird das Ganze durch die erste gemerkte Zeichenkette (Ziffer Strich 4 weitere Ziffern) dann ein Unterstich, und dann die zweite gemerkte Zeichenkette (einzelne Ziffer).

Danke für die Erklärung, um die Abschnitte (Suchen/Ersetzen) zu trennen nimmst du hier also # damit es übersichtlicher ist. Das kenne ich noch von sed. Gruppieren mit demaskierter Klammer. Ok. Wenn ich das nun so eingebe beschwert sich rename jedoch:

\1 better written as $1

Mit $1, jedoch ohne Gruppen, hatte ich da zuvor sogar getestet, da kam jedoch eine Meldung ähnlich "kann auf $1 nicht zugreifen da nicht referenziert".

Nehme ich statt dessen jedoch das $-Zeichen erhalte ich gar keine Änderung oder Ausgabe, nicht mal mit der -v Option von rename.

1
rename -v 's#\(\d-\d{4}\)\([0-9]\)\.#$1_$2#'

bongobong

(Themenstarter)
Avatar von bongobong

Anmeldungsdatum:
12. Dezember 2008

Beiträge: 1820

Wohnort: Hamburg

track schrieb:

Das ganze geht noch eleganter mit Hilfe eines Lookbehind- Ausdrucks, zusätzlich zur Back Reference:

track@track:~$ echo -e 'A-12345.jpg\n0-12341.jpg'  |  perl -pe 's/(?<=\d-\d{4})(\d)\./_\1./'
A-12345.jpg
0-1234_1.jpg 

... p.s.: es geht auch ohne Back Reference, wenn man beides, Lookbehind + Lookahead verwendet:

track@track:~$ echo -e 'A-12345.jpg\n0-12341.jpg'  |  perl -pe 's/(?<=\d-\d{4})(?=\d\.)/_/'
A-12345.jpg
0-1234_1.jpg 

LG,

track

Danke, dass sieht jetzt aber doch noch etwas komplizierter für mich aus. Habe das "perl" auch nur erwähnt, da in der manpage von rename steht, dass perlexpr (Perl expression) geutzt werden und ich davon ausging, dass diese sich etwas von regulären regulären Ausdrücken unterscheiden ☺

track

Avatar von track

Anmeldungsdatum:
26. Juni 2008

Beiträge: 7174

Wohnort: Wolfen (S-A)

Dies "Lookahead/-behind" - Gedöns erschreckt einen nur auf den ersten Blick.

Im Grunde sind das auch nur spezielle Gruppierungen, wie Du sie bisher auch schon hattest. Nur dass sie nicht "verbraucht" (also ersetzt) werden.
Dazu haben sie am Anfang die Markierung (?=...) bzw. (?<=...) (für "rückwärts").

Mehr ist es gar nicht. - lies es einfach mal im verlinkten Tutorium nach !

Oder anhand des Beispiels oben, ist es beides gleichwertig:

track@track:~$ echo -e 'A-12345.jpg\n0-12341.jpg'  |  perl -pe 's/(?<=\d-\d{4})(?=\d\.)/_/'
A-12345.jpg
0-1234_1.jpg
track@track:~$ echo -e 'A-12345.jpg\n0-12341.jpg'  |  perl -pe 's/(\d-\d{4})(\d\.)/\1_\2/'
A-12345.jpg
0-1234_1.jpg 

LG,

track

bongobong

(Themenstarter)
Avatar von bongobong

Anmeldungsdatum:
12. Dezember 2008

Beiträge: 1820

Wohnort: Hamburg

@track

Danke, ich bekomme es jedoch mit deinen Beispielen nicht hin. Lasse ich alles vor und inkl. | weg. Ich konnte auch weder in der Hilfe noch in der Manpage etwas zu der Option e bzw. -pe von Perl finden. Lasse ich "e" weg erhalte ich "Datei oder Verzeichnis nicht gefunden". Lasse ich "p" oder alles weg erhalte ich weder Änderung noch Ausgabe.

track

Avatar von track

Anmeldungsdatum:
26. Juni 2008

Beiträge: 7174

Wohnort: Wolfen (S-A)

Das perl -pe ' ... ' ist einfach nur das Gerüst für einen Perl-Einzeiler. Betrachte es zunächst mal einfach als reine Formsache.

Den Rest, das was zwischen den 'Hochkommas' steht, kannst Du einfach 1:1 ins Perl- rename übernehmen.
Vorsichtshalber vielleicht zum testen evt. mit der Option rename -nv ... dann siehst Du, was es tun würde.

LG,

track

bongobong

(Themenstarter)
Avatar von bongobong

Anmeldungsdatum:
12. Dezember 2008

Beiträge: 1820

Wohnort: Hamburg

Hallo und Danke

Hat etwas gedauert bis ich zum testen gekommen bin, aber es funktioniert nun:

1
2
3
4
5
6
7
8
$ ls
A-12341.jpg  A-12345.jpg

$ rename -vn 's/(?<=\d-\d{4})(?=\d\.)/_/' *
0-12341.jpg renamed as 0-1234_1.jpg

$ rename -vn  's/(\d-\d{4})(\d\.)/$1_$2/'  *
0-12341.jpg renamed as $1_$2jpg

Eine Frage noch zum ersten Befehl:

Also ich erstelle mit "(?⇐\d-\d{4})" eine Gruppe, welche Namen speichert, die aus einer Zahl, einem Bindestrich und vier Zahlen bestehen.

Auch speichere ich eine zweite Gruppe mit "(\d\.)" in der die Zahl gespeichert wird, welche vor dem Punkt kommt.

Woher weiß die Funktion nun, dass der Unterstrich zwischen den beiden Gruppen gesetzt werden soll "/_/". Beim zweiten Befehl ist dass ja recht klar.

track

Avatar von track

Anmeldungsdatum:
26. Juni 2008

Beiträge: 7174

Wohnort: Wolfen (S-A)

Nee, beim Lookbefore und Lookbehind wird die Gruppe ja gerade nicht gespeichert und nicht ersetzt. Sondern es wird nur geguckt, ob sie "vor" bzw. "hinter" dem betrachteten Punkt vorhanden ist. Mehr nicht.

Und da hier die "betrachtete Gruppe" für beide der selbe (und leer) ist, wird diese leere Gruppe, nämlich genau der (leere) Zwischenraum zwischen dem Ziffernmuster(1) und der letzten Ziffer mit Punkt dahinter(2) durch den Unterstrich ersetzt.

LG,

track

bongobong

(Themenstarter)
Avatar von bongobong

Anmeldungsdatum:
12. Dezember 2008

Beiträge: 1820

Wohnort: Hamburg

Nach 3 mal lesen verstanden, Danke 👍

Antworten |