PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : sed Problem mit Sonderzeichen



clumsy
03-03-2005, 11:18
Hi,

ich schreib mir grad nen kleines Script. Dazu brauch ich zB von einem Pfad wie /stuff/MP3s/Interpret/Album nur das Album. Ich wollte mir sed nach dem letzten Vorkommen von / suchen und alles danach ist dann das Album. Aber das klappt nicht.


for i in `pwd`; do echo $i | sed s/$\//HALLO/g; done
Was ich nicht verstehe ist, wenn ich sed s/abc /HALLO/g mache, funktioniert das, wenn ich aber "/" ersetzen will mit sed s/\//HALLO/g geht das nicht, was mach ich falsch?

THX
clumsy

peschmae
03-03-2005, 12:12
Also Grundsätzlich steht das $ für das Ende der Zeile wenn es am Ende deines Regulären Ausdrucks steht, nicht "das letzte /" oder so ähnlich.
Gehen würde z.B. der Ausdruck: s#.*/##

Noch einfacher ist wenn du das Progrämmchen basename verwendest. Also "basename /home/zeug/bla/irgendwas" gibt irgendwas zurück.

MfG Peschmä

clumsy
03-03-2005, 16:42
Gehen würde z.B. der Ausdruck: s#.*/##
Kannst du mir den Ausdruck bitte kurz erklären? Versteh den nicht...



Noch einfacher ist wenn du das Progrämmchen basename verwendest. Also "basename /home/zeug/bla/irgendwas" gibt irgendwas zurück.


So hab ich jetzt gemacht.
Aber wie bekomm ich aus "/Irgend/.../was/Interpret/Album/" den Interpret?
Am besten allgemein:
Wie bekomme ich aus einem String den hinteren Teil raus wie zB blabla_test_schrott.mp3 wobei ich nur "schrott" haben will, und die "_" könnten wegen mir auch alles mögliche (auch unterschiedlich) sein.
Ich denk mir das so: Suche das letzte Vorkommen eines best. Trennzeichens und nimm den Rest danach.

THX nochmal :)

peschmae
03-03-2005, 19:34
Kannst du mir den Ausdruck bitte kurz erklären? Versteh den nicht...

.: irgend ein Zeichen
*: 0 bis bieliebige vom vorhergehenden
/: ein / halt

Bei Regexps in Sed ist jeder Teil immer so gross wie er sein kann (von links nach rechts). Also das .*/ passt auf so viel Zeichen wie möglich und ein abschliessendes / und die werden dann ahlt durch nix ersetzt.



Aber wie bekomm ich aus "/Irgend/.../was/Interpret/Album/" den

z.B. mit
echo blabla| sed "s#.*/\(.*\)/.*/##"

Oder auch mit


VAR=/asdf/Irgend/.../was/Interpret/Album/
VAR=${VAR%/*/}
VAR=${VAR##*/}
echo $VAR

gemäss http://www.tldp.org/LDP/abs/html/parameter-substitution.html#PATTMATCHING

MfG Peschmä

Jasper
03-03-2005, 21:53
z.B. mit
echo blabla| sed "s#.*/\(.*\)/.*/##"


da fehlt die backreferenz \1 im ersetzungsteil:

sed "s#.*/\(.*\)/.*/#\1#"


-j

clumsy
03-03-2005, 23:55
danke, der link ist prima! hat mir viel geholfen, und jetzt hab ich's auch halbwegs verstanden....

Aber das hier:
sed "s#.*/\(.*\)/.*/#\1#" hab ich noch nicht wirklich verstanden. Was bedeuten denn die Rauten? Hab ich das richtig verstanden, dass man entweder Rauten oder "/" hernehmen kann? Ich arbeite mit sed immer so in der Art:
sed s/^[0-9][0-9]/blabla/g
Und was macht "#\1#" genau?
Danke für Deine Geduld :)

noch ne andere Frage:
ich hab in meinem Script ne Userabfrage (j/n). Wie decke ich am besten alle möglichen Fälle ab, falls der User zB "j" oder "J" oder "ja" usw eingibt? ich hab das mit case gelöst...gibts da noch ne andere schöne Möglichkeit?

peschmae
04-03-2005, 07:48
Aber das hier:
sed "s#.*/\(.*\)/.*/#\1#" hab ich noch nicht wirklich verstanden. Was bedeuten denn die Rauten? Hab ich das richtig verstanden, dass man entweder Rauten oder "/" hernehmen kann? Ich arbeite mit sed immer so in der Art:
sed s/^[0-9][0-9]/blabla/g

Achso, sorry. Genau. Hat mich am Anfang auch verwirrt aber mittlerweiel nehme ich (fast) immer die Rauten. Wieso?
Wenn du / nimmst musst du alle / die aus Pfaden stammen durch \/ ersetzen. Das suckt.
Du musst übrigens nicht die Raute nehmen, eine Pipe z.B. tuts auch:


echo blasdfasdfbl | sed s|bla|wasanderes|
echo asdfbla | sed "sfasd\ffnixdaf"

wobe beim zweiten der Buchstabe f der Trenner ist :D



Und was macht "#\1#" genau?

Das fügt den Teil der zwischen den (ersten) \( \) war wieder ein.



Danke für Deine Geduld :)
Bitte :)



noch ne andere Frage:
ich hab in meinem Script ne Userabfrage (j/n). Wie decke ich am besten alle möglichen Fälle ab, falls der User zB "j" oder "J" oder "ja" usw eingibt? ich hab das mit case gelöst...gibts da noch ne andere schöne Möglichkeit?

Du kannst auch sowas machen:


read i
i=$(echo $i | tr A-Z a-z)
if [ "$i" = "j" -o "$i" = "jupp" -o "$i" = "ja" -o "$i" = "yes" ]; then

fi


Gemäss man test einfach die = Abfrage mit -o verknüpfen. Die Obige Zeile mit dem tr konvertiert die Eingabe in Kleinbuchstaben.

MfG Peschmä

clumsy
04-03-2005, 10:48
Cool, danke!

Mein Script läuft mittlerweile teilweise. Hab noch ein paar Fragen:

-> Wie lassen sich Usereingaben bevorzugen? Also wenn ich mein script zB mit --album "name" aufrufe, soll $ALBUM immer "name" beinhalten.
-> Bei der Ausführung meines Scripts ist die Reihenfolge der Schalter wichtig, sonst gibts Unsinn. Durch welche Technik kann ich das vermeiden?

Hier noch mein erstes etwas grösseres Script :-)

peschmae
04-03-2005, 11:21
-> Wie lassen sich Usereingaben bevorzugen? Also wenn ich mein script zB mit --album "name" aufrufe, soll $ALBUM immer "name" beinhalten.

Das machst du doch schon indem du ALBUM nur einliest wenn die Variable nicht schon gesetzt ist.



-> Bei der Ausführung meines Scripts ist die Reihenfolge der Schalter wichtig, sonst gibts Unsinn. Durch welche Technik kann ich das vermeiden?


Wie ist das zu verstehen? So wie du das machst - shift und so - spielt doch die Parameterreihenfolge eben gerade keine Rolle :confused:

MfG Peschmä

clumsy
05-03-2005, 18:02
Wie ist das zu verstehen? So wie du das machst - shift und so - spielt doch die Parameterreihenfolge eben gerade keine Rolle :confused:


das ergebnis ist ein anderes wenn ich zB "mp3sort.sh --album "MEINALBUM" -a aufrufe oder "mp3sort.sh -a --album "MAINALBUM". Im 2. Fall würde er, nachdem er bereits alle Dateien umbenannt hat, die Variable $ALBUM neu setzen. Dabei wäre es natürlich sinnvoll, wenn zuerst ALBUM gesetzt wird und dann der Rest abgearbeitet wird.

weiss nur nicht so genau, wie ich sowas berücksichtigen kann....

peschmae
05-03-2005, 19:19
Achso. Ich hatte nur schnell drübergeguckt und mir nicht genau überlegt wer jetzt was macht und so.

Dann darfst du halt auf den gefunden Paramenter -a nicht *sofort* diese Aktionen ausführen sondern setzt irgend einen Flag (Variable) im Sinne von -awarda und wertest den erst aus, nachdem du alle Kommandozeilenparameter eingelesen hast.

also:


-i|--interpret)
INTERPRET=$2;
shift
;;
-a|--automatic)
AUTOMATIC=true
blabla
esac
# shift
done

if [ $AUTOMATIC ]; then
for TITLE in *.mp3; do
getBasename;
getNumberTrue;

if [ $? -eq 0 ]; then
if [ -z $ANTWORT ]; then
echo "Keine Titelnummer im Dateinamen enthalten. Soll ich die Titel automatisch nummerieren? (j/n)"
read ANTWORT;
fi
case "$ANTWORT" in
j | J | Ja | ja | JA | jA)
((COUNTER=$COUNTER+1));
if [ $COUNTER -lt 10 ]; then
NUMBER="_-_0`echo $COUNTER`_-_";
else
NUMBER="_-_`echo $COUNTER`_-_";
fi
;;
n | N )
NUMBER="_-_";
;;
esac;
elif [ $? -eq 1 ]; then
getNumber;
fi
getTrack;
build;
fi


MfG Peschmä