mit dateinamen-teilen arbeiten

Warum Debian und/oder eine seiner Spielarten? Was muss ich vorher wissen? Wo geht es nach der Installation weiter?
Antworten
ali
Beiträge: 50
Registriert: 26.06.2007 09:37:30

mit dateinamen-teilen arbeiten

Beitrag von ali » 25.12.2007 15:08:12

hallo, ich sitze gerade vor einem kleinen shell-script, das mit dateien etwas macht. ich stehe gerade vor dem problem, das ich zb aus dem dateinamen "backup_2xy49.rar" nur den dateinamen OHNE extension filtern kann, und damit weiterarbeiten kann... grep viel mir spontan ein, da es sich eigentlich nur um eine regexp anwendung handeln kann (da die regeln nicht immer so simpel sein können). ich bin zwar kein anfänger in sachen regexp, aber mir fehlt einfach das passende tool, das mit strings arbeitet, und mir nur den teil zurückgibt, auf den die regexp matcht. wie gesagt, grep eignet sich nicht dafür, da das ding gleich die ganze zeile zurückgibt...


gibt mir nen programm-tipp wenn ihr eins kennt!

danke

Benutzeravatar
ThorstenS
Beiträge: 2875
Registriert: 24.04.2004 15:33:31

Beitrag von ThorstenS » 25.12.2007 15:15:16

Die Shell kann das auch alleine

Code: Alles auswählen

#!/bin/bash
DATEI=backup_2xy49.rar
NAME=${DATEI%%.rar} && echo $NAME
backup_2xy49
EXTENSION=${DATEI#*.} && echo $EXTENSION
rar

ali
Beiträge: 50
Registriert: 26.06.2007 09:37:30

Beitrag von ali » 25.12.2007 16:51:26

danke, schonwieder was gelernt, kannst mir auch noch sagen, wie sich das verfahren nennt, damit ich mich auf ner man-page informieren kann?

nichtsdestotrotz würde ich auch gerne eine variante an der hand haben, um das mit regexp zu lösen, denn nicht immer lässt es sich so einfach lösen, wenn man verschieden variierende dateinamen hat, wo man eventuell vorne etwas wegschneiden muss, oder in der mitte...

ich denke da an den fall mit den rar dateien, das alte volume-format war ja
xy.rar
xy.r00
sy.r01
...

das neue sieht so aus
sy.part1.rar
sy.part2.rar
...

bei dem neuen format würde ich auch gern .part*.rar wegschneiden. wie müsste das dann lauten?

danke

ali
Beiträge: 50
Registriert: 26.06.2007 09:37:30

Beitrag von ali » 25.12.2007 17:56:53

hab mir eben mal einen RE ausdruck überlegt:

Code: Alles auswählen

(.*?)(\.part[0-9]+)?\.rar
er müsste bei allen diesen dateien, wenn man den inhalt des ersten klammernpaars "(.*?)" ausgibt
bla.part1.rar
bla.rar
bla.part02.rar
bla.part005.rar
immer "bla" zurückliefern, also den dateinamen... fehlt mir nur noch ein tool, das diesen ausdruck korrekt umsetzt... hab diesen ausdruck bereits mit einem regex-debugger getestet, dieser ausdruck ist 100%ig richtig!

bin schon am verzweifeln :(

chr.gogolin
Beiträge: 441
Registriert: 12.10.2005 23:09:28
Lizenz eigener Beiträge: MIT Lizenz
Kontaktdaten:

Beitrag von chr.gogolin » 25.12.2007 18:09:00

Du suchst "sed"!

Ein kleines Minimalbeispiel, das mit einer einfacheren regexp arbeitet und ungefähr das machst was du willst ist:

Code: Alles auswählen

sed 's/\(.*\)\.rar/\1/'
Die liste von Dateinamen mit Endungen einfach "durchpipen".
"Linux supports the notion of a command line or a shell for the same reason that only children read books with only pictures in them." - Bill Garrett

ali
Beiträge: 50
Registriert: 26.06.2007 09:37:30

Beitrag von ali » 25.12.2007 18:24:28

danke, dachte schon, ich müsst mir nen neues board suchen, weil ich so selten antworten auf meine fragen bekomme :D

btt: ich dachte schon, ich wäre am ziel
hab mal meinen ausdruck sed-konform gemacht, scheint aber nich zu klappen...

Code: Alles auswählen

echo "www.part1.rar" "xyz.rar" | sed -e 's/\(.*\?\)\(\.part[0-9]\+\)\?\.rar/\1/'
www.part1.rar xyz
wie man sieht, klappts mit xyz.rar, aber bei dem part1 dazwischen willer mir das immer wieder mit aufdrücken. haste da eventuell eine idee?

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

Beitrag von Meillo » 25.12.2007 18:37:20

ali hat geschrieben:

Code: Alles auswählen

echo "www.part1.rar" "xyz.rar" | sed -e 's/\(.*\?\)\(\.part[0-9]\+\)\?\.rar/\1/'
www.part1.rar xyz
wie man sieht, klappts mit xyz.rar, aber bei dem part1 dazwischen willer mir das immer wieder mit aufdrücken. haste da eventuell eine idee?
Ich vermute stark, dass das Problem ist, dass beide Strings in einer Zeile sind!
Mach mal eine geeignente Eingabe (Stings in eine Textdatei schreiben, oder `ls *.*' oder so) dann sollte es auch funzen.

Will auch noch ein bisschen Code dazu werfen:

Code: Alles auswählen

 ls *.* | sed -e 's/\.part[0-9]\+// ; s/\.rar//'
(Das entfernt jeweils nur den entsprechenden Teil des Strings ... finde ich einfach zu handhaben.)
Use ed once in a while!

ali
Beiträge: 50
Registriert: 26.06.2007 09:37:30

Beitrag von ali » 25.12.2007 18:54:43

Meillo hat geschrieben:
ali hat geschrieben:

Code: Alles auswählen

echo "www.part1.rar" "xyz.rar" | sed -e 's/\(.*\?\)\(\.part[0-9]\+\)\?\.rar/\1/'
www.part1.rar xyz
wie man sieht, klappts mit xyz.rar, aber bei dem part1 dazwischen willer mir das immer wieder mit aufdrücken. haste da eventuell eine idee?
Ich vermute stark, dass das Problem ist, dass beide Strings in einer Zeile sind!
Mach mal eine geeignente Eingabe (Stings in eine Textdatei schreiben, oder `ls *.*' oder so) dann sollte es auch funzen.
ein echo "www.part1.rar" habich auch versucht, es kam immer ein string mit dem "part1" zurück, mir scheint es fast so, als würde sed das von mir definierte lazy "\(.*\?\)" (das "?") ignorieren, und bis hinter part1 parsen, dann den teil "\(\.part[0-9]\+\)\?" komplett ignorieren (also ? bedeutet 0 oder 1mal, sed nimmt hier wohl 0, weil es schon hinter dem part angekommen ist) und macht dann bei .rar weiter...

falls jemand dazu ne erklärung hat, wäre interessant zu wissen, wieso sed das macht, was es macht :D
Meillo hat geschrieben: Will auch noch ein bisschen Code dazu werfen:

Code: Alles auswählen

 ls *.* | sed -e 's/\.part[0-9]\+// ; s/\.rar//'
(Das entfernt jeweils nur den entsprechenden Teil des Strings ... finde ich einfach zu handhaben.)
das klappt, okay, daran hatte ich nicht gedacht, man lernt immer wieder was dazu :)

danke

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

Beitrag von Meillo » 26.12.2007 12:35:15

ali hat geschrieben:ein echo "www.part1.rar" habich auch versucht, es kam immer ein string mit dem "part1" zurück, mir scheint es fast so, als würde sed das von mir definierte lazy "\(.*\?\)" (das "?") ignorieren, und bis hinter part1 parsen, dann den teil "\(\.part[0-9]\+\)\?" komplett ignorieren (also ? bedeutet 0 oder 1mal, sed nimmt hier wohl 0, weil es schon hinter dem part angekommen ist) und macht dann bei .rar weiter...

falls jemand dazu ne erklärung hat, wäre interessant zu wissen, wieso sed das macht, was es macht :D
... das war der Grund weshalb ich meine "einfachere" Lösung vorgeschlagen habe, denn RegExp sind nicht trivial.
Der Teil der den "part" matchen soll, bleibt leer, weil die erste Klammer gleich alles für sich wegnimmt. RegExp sind standardmäßig "greedy" also "gierig", sie nehmen was sie kriegen. Das ? stellt ja offen, ob der Ausdruck davor vorkommt, oder nicht. Der RegExp passt nunmal auf zwei Arten, einmal wenn der Part-Teil in die erste Klammer fällt und die zweite gar nicht vorkommt, und einmal, wenn der Part-Teil in die zweite Klammer fällt.
... kappiert?

deshalb sollte man bei optionalen Elementen etwas mehr aufpassen und lieber alternative Lösungen wählen.
Use ed once in a while!

ali
Beiträge: 50
Registriert: 26.06.2007 09:37:30

Beitrag von ali » 26.12.2007 21:58:27

Meillo hat geschrieben:RegExp sind standardmäßig "greedy" also "gierig", sie nehmen was sie kriegen. Das ? stellt ja offen, ob der Ausdruck davor vorkommt, oder nicht. Der RegExp passt nunmal auf zwei Arten, einmal wenn der Part-Teil in die erste Klammer fällt und die zweite gar nicht vorkommt, und einmal, wenn der Part-Teil in die zweite Klammer fällt.
... kappiert?
standardmäßig greedy, jo, schon klar, aber das fragezeichen hat zwei bedeutungen, einmal kann es bedeuten, das das element davor 0 oder 1 mal vorkommen darf, und einmal, wenn es hinter einem quantifier steht, das dieser quantifier lazy wird (bei mir also hinter dem * in der ersten klammer!), so müsste mein regexp eigentlich anders matchen, denn die abstrakte maschine müsste eigentlich bei einem lazy-quatifier nach jedem buchstaben versuchen, ob nich die nachfolgenden definitionen auch passen... aber nungut, sollte ich einfach als schlamperei abhaken und gut ist :)

deine version is auch die elegantere, weil die die teile, sofern sie vorkommen, rauslöscht, so kann man es noch beliebig erweitern, zb .zip, .tar.gz etc :D

danke

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

Beitrag von Meillo » 27.12.2007 12:44:59

ali hat geschrieben:standardmäßig greedy, jo, schon klar, aber das fragezeichen hat zwei bedeutungen, einmal kann es bedeuten, das das element davor 0 oder 1 mal vorkommen darf, und einmal, wenn es hinter einem quantifier steht, das dieser quantifier lazy wird (bei mir also hinter dem * in der ersten klammer!), so müsste mein regexp eigentlich anders matchen, denn die abstrakte maschine müsste eigentlich bei einem lazy-quatifier nach jedem buchstaben versuchen, ob nich die nachfolgenden definitionen auch passen... aber nungut, sollte ich einfach als schlamperei abhaken und gut ist :)
ahh,,, da hab ich nicht genau genug geschaut und auch auch deinen vorherigen Post nicht gut genug gelesen :roll:

... ich weiß nicht, ob sed (vermutlich gsed in unserem Fall) das unterstützt, also das Fragezeichen als ungreedy-Modifier ... aber falls es unterstützt wird, sollte es eigentlich wie von dir beschrieben ausgewertet werden (klingt jedenfalls logisch, in meinen Ohren)
deine version is auch die elegantere, weil die die teile, sofern sie vorkommen, rauslöscht, so kann man es noch beliebig erweitern, zb .zip, .tar.gz etc :D
man darf aber auch nicht vergessen, dass meine Version die Position der Teilstücke im String _nicht_ berücksichtigt, wohingegen das andere Pattern, dies sehr wohl tut!
Für deinen Fall ist das wohl unerheblich ... nur sollte man es nicht vergessen.

danke
hat mir viel Spaß gemacht :D
Use ed once in a while!

ali
Beiträge: 50
Registriert: 26.06.2007 09:37:30

Beitrag von ali » 27.12.2007 22:24:28

Meillo hat geschrieben:man darf aber auch nicht vergessen, dass meine Version die Position der Teilstücke im String _nicht_ berücksichtigt, wohingegen das andere Pattern, dies sehr wohl tut!
Für deinen Fall ist das wohl unerheblich ... nur sollte man es nicht vergessen.
na, das habich ja direkt erweitert, bei mir berichtigt das nun auch die position, und zwar ists bei mir das ende des strings:

Code: Alles auswählen

 sed -e 's/\.rar$// ; s/\.zip$// ; s/\.part[0-9]\+$//'
zuerst .rar und/oder .zip entfernen, dann noch, falls vorhanden .partx, fertig :) (man beachte das $, steht für stringende)

und es funktioniert :)

Antworten