Discussion:
shellscript: letzte 3 Zeichen eines Textes abschneiden
(zu alt für eine Antwort)
Ralf Kleemann
2007-01-27 09:58:42 UTC
Permalink
Hallo,

ich möchte von einem Text die letzten 3 Zeichen (z.b.".ts") entfernen:

mit
a="abc.ts"
echo "${a:(-3)}"
.ts

ist es mir nur gelungen, daß vorne Zeichen entfernt werden.


Geht dies auch mit grep -o?

Gruß Ralf
Alexander Bartolich
2007-01-27 10:53:35 UTC
Permalink
Post by Ralf Kleemann
mit
a="abc.ts"
echo "${a:(-3)}"
.ts
ist es mir nur gelungen, daß vorne Zeichen entfernt werden.
man bash
# ${parameter:offset}
# ${parameter:offset:length}
# [...]
# If offset evaluates to a number less than zero, the
# value is used as an offset from the end of the value of
# parameter.

Funktioniert wie angepriesen ...
Aber einige Zeilen weiter findet sich das hier:

# ${#parameter}
# The length in characters of the value of parameter is
# substituted.

echo ${a:0:${#a}-3}
Post by Ralf Kleemann
Geht dies auch mit grep -o?
Nein. Aber mit sed:

echo "${a}" | sed 's/\(.*\)...$/\1/'

--
Ralf Kleemann
2007-01-27 18:49:24 UTC
Permalink
Post by Alexander Bartolich
Post by Ralf Kleemann
Geht dies auch mit grep -o?
echo "${a}" | sed 's/\(.*\)...$/\1/'
ich habe gedacht, ich hätte reguläre Ausdrücke ein wenig kapiert, aber
die Funktion diese Ausdrucks verstehe ich überhaupt nicht.

Gruß Ralf
Sebastian Hungerecker
2007-01-27 19:07:39 UTC
Permalink
Post by Ralf Kleemann
Post by Alexander Bartolich
echo "${a}" | sed 's/\(.*\)...$/\1/'
ich habe gedacht, ich hätte reguläre Ausdrücke ein wenig kapiert, aber
die Funktion diese Ausdrucks verstehe ich überhaupt nicht.
Die Klammern mit dem Backslash davors sagen, dass das, was zwischen ihnen
steht, in \1 gespeichert werden soll. ".*" ist einfach irgendein Text.
"..." sind drei beliebige Zeichen und $ ist das Zeilenende. Also wird
hier irgendwas gefolgt von drei Zeichen durch irgendwas ohne die drei
Zeichen ersetzt. Nach meinem RegEx-Verständnis ist das aber das gleiche
wie 's/...$//' (ersetze die drei letzten Zeichen durch gar nichts), was
etwas einfacher ist.
--
Ist so, weil ist so
Bleibt so, weil war so
Ralf Kleemann
2007-01-27 19:55:06 UTC
Permalink
Post by Sebastian Hungerecker
Nach meinem RegEx-Verständnis ist das aber das gleiche
wie 's/...$//' (ersetze die drei letzten Zeichen durch gar nichts), was
etwas einfacher ist.
Stimmt, das funktioniert wie gewünscht.
Diese einfache Funktion hätte ich auch verstanden.

Gruß Ralf
Alexander Bartolich
2007-01-27 19:11:40 UTC
Permalink
Post by Ralf Kleemann
Post by Alexander Bartolich
[...]
echo "${a}" | sed 's/\(.*\)...$/\1/'
ich habe gedacht, ich hätte reguläre Ausdrücke ein wenig
kapiert, aber die Funktion diese Ausdrucks verstehe ich
überhaupt nicht.
Beliebig viele beliebige Zeichen: .*

Drei beliebige Zeichen am Ende der Zeile: ...$

Beliebig viele beliebige Zeichen, gefolgt von drei beliebige Zeichen
am Ende der Zeile: .*...$

Die Klammern erfüllen zwei Funktionen. Zum einen kann damit "oder"
implementieren, also \(abc\|def\)". Zum anderen ist der mit den
Klammern erfasste Text auf Ersetzungsseite verfügbar. \1 steht für
das erste Klammenpaar, \2 für das zweite, etc.

--
Juergen P. Meier
2007-01-28 08:19:17 UTC
Permalink
Post by Alexander Bartolich
echo "${a}" | sed 's/\(.*\)...$/\1/'
Ein sed 's/...$//' reicht auch ;)

Juergen
--
Juergen P. Meier - "This World is about to be Destroyed!"
end
If you think technology can solve your problems you don't understand
technology and you don't understand your problems. (Bruce Schneier)
Ralf Kleemann
2007-01-28 10:05:55 UTC
Permalink
Post by Juergen P. Meier
Post by Alexander Bartolich
echo "${a}" | sed 's/\(.*\)...$/\1/'
Ein sed 's/...$//' reicht auch ;)
Kann ich mit sed auch ein String in Teilstrings zerlegen oder gibt es
dafür einfachere Möglichkeiten?

Ich habe versucht den folgenden String
a="abc - defg - hij - klmn"
in "abc" und "defg - hij - klmn" zu zerlegen. Dabei soll die Anzahl der
"-" in a egal sein.
Post by Juergen P. Meier
echo $a| sed 's/ - .*//'
abc

aber
Post by Juergen P. Meier
echo $a| sed 's/.* - //'
klmn

funktioniert nicht.

Ich muß ohne grep -o auskommen, da in diesem Fall das grep den Parameter
-o nicht kennt.

Gruß Ralf








Gruß Ralf
Ralf Kleemann
2007-01-28 10:27:42 UTC
Permalink
Post by Ralf Kleemann
aber
Post by Juergen P. Meier
echo $a| sed 's/.* - //'
klmn
funktioniert nicht.
a="abc - defg - hij - klmn"
b=`echo ${a#*-}`
echo "=$b="
=defg - hij - klmn=

funktioniert, mir ist aber nicht klar warum in der Variable b nicht wie
erwartet ein Leerzeichen vor defg.. ist?

Gruß Ralf
Helmut Hullen
2007-01-28 10:43:00 UTC
Permalink
Hallo, Ralf,
Post by Ralf Kleemann
Post by Ralf Kleemann
b=`echo ${a#*-}`
echo "=$b="
a="abc - defg - hij - klmn"
=defg - hij - klmn=
funktioniert, mir ist aber nicht klar warum in der Variable b nicht
Weil Du bei der Beschaffung von "b" "echo" dazwischengeschaltet hast.

Versuch mal

c=${a#*-}
echo "=$c="

Viele Gruesse!
Helmut
Helmut Schellong
2007-01-28 10:35:26 UTC
Permalink
Post by Ralf Kleemann
Post by Juergen P. Meier
Post by Alexander Bartolich
echo "${a}" | sed 's/\(.*\)...$/\1/'
Ein sed 's/...$//' reicht auch ;)
Kann ich mit sed auch ein String in Teilstrings zerlegen oder gibt es
dafür einfachere Möglichkeiten?
Ich habe versucht den folgenden String
a="abc - defg - hij - klmn"
in "abc" und "defg - hij - klmn" zu zerlegen. Dabei soll die Anzahl der
"-" in a egal sein.
127] expr 'aaa - bbb - ccc' : '\([^ -]\{1,\}\)'
aaa
128] expr 'aaa - bbb - ccc' : '[^ -]\{1,\}[ -]*\(.\{1,\}\)'
bbb - ccc
129]
--
Mit freundlichen Grüßen
Helmut Schellong ***@schellong.biz
www.schellong.de www.schellong.com www.schellong.biz
http://www.schellong.de/c.htm
Helmut Hullen
2007-01-28 10:38:00 UTC
Permalink
Hallo, Ralf,
Post by Ralf Kleemann
Kann ich mit sed auch ein String in Teilstrings zerlegen oder gibt es
dafür einfachere Möglichkeiten?
Ich habe versucht den folgenden String
a="abc - defg - hij - klmn"
in "abc" und "defg - hij - klmn" zu zerlegen. Dabei soll die Anzahl
der "-" in a egal sein.
Da gibt es neben "sed" auch noch die eingebauten Möglichkeiten der
"bash" sowie "cut".
Du solltest wenigstens wissen, ob Du als Merkmal eine bestimmte Zahl von
Zeichen nimmst oder aber ein bestimmtes Zeichen als Trenner zwischen
"links" und "rechts".

Wahre Könner nehmen natürlich "awk" ...

Viele Gruesse!
Helmut
Heike C. Zimmerer
2007-01-28 11:26:54 UTC
Permalink
Post by Ralf Kleemann
Post by Juergen P. Meier
Post by Alexander Bartolich
echo "${a}" | sed 's/\(.*\)...$/\1/'
Ein sed 's/...$//' reicht auch ;)
Kann ich mit sed auch ein String in Teilstrings zerlegen oder gibt es
dafür einfachere Möglichkeiten?
Es gibt einfachere; sie wurden genannt. Shell-Bordmittel tun's auch.
Post by Ralf Kleemann
Ich habe versucht den folgenden String
a="abc - defg - hij - klmn"
in "abc" und "defg - hij - klmn" zu zerlegen. Dabei soll die Anzahl der
"-" in a egal sein.
echo "${a%% -*}"
echo "${a#*- }"
Juergen P. Meier
2007-01-29 06:47:51 UTC
Permalink
Post by Ralf Kleemann
Post by Juergen P. Meier
Post by Alexander Bartolich
echo "${a}" | sed 's/\(.*\)...$/\1/'
Ein sed 's/...$//' reicht auch ;)
Kann ich mit sed auch ein String in Teilstrings zerlegen oder gibt es
dafür einfachere Möglichkeiten?
Was meinst du genau mit "teilstring"?
Post by Ralf Kleemann
Ich habe versucht den folgenden String
a="abc - defg - hij - klmn"
in "abc" und "defg - hij - klmn" zu zerlegen. Dabei soll die Anzahl der
"-" in a egal sein.
Du meinst in zwei Variablen? sed verarbeitete nur einen Stream (daher
der name).
Post by Ralf Kleemann
Post by Juergen P. Meier
echo $a| sed 's/ - .*//'
abc
aber
Post by Juergen P. Meier
echo $a| sed 's/.* - //'
klmn
funktioniert nicht.
Das nennt man "greedy match": der regulaere Ausdruck geht auf den
groestmoeglichen Match.
Post by Ralf Kleemann
Ich muß ohne grep -o auskommen, da in diesem Fall das grep den Parameter
-o nicht kennt.
Du kannst sed den greedy match nicht portabel austreiben, du kannst
aber einfach umgekehrte Logik im Patternmatching verwenden:

echo $a | sed 's/[^-]* - //'

Das [^-] matcht auf jedes Zeichen ausser Newline (sed arbeitet
prinzipiell Zeilenweise) und '-'.

Juergen
--
Juergen P. Meier - "This World is about to be Destroyed!"
end
If you think technology can solve your problems you don't understand
technology and you don't understand your problems. (Bruce Schneier)
Ralf Kleemann
2007-01-29 20:42:48 UTC
Permalink
Post by Juergen P. Meier
Du meinst in zwei Variablen?
Ja, ich möchte die beiden Teile in zwei Variablen speichern.

Dank der vielen Tipps hier, funktioniert inzwischen mein script so wie
es soll.

Gruß Ralf

Helmut Hullen
2007-01-27 10:55:00 UTC
Permalink
Hallo, Ralf,
Post by Ralf Kleemann
ich möchte von einem Text die letzten 3 Zeichen (z.b.".ts")
mit
a="abc.ts"
echo "${a:(-3)}"
.ts
ist es mir nur gelungen, daß vorne Zeichen entfernt werden.
So soll der negative Offset ja auch funktionieren.
Mit den Optionen wird bestimmt, was beibehalten wird, nicht was entfernt
wird.

Was allemal funktionieren sollte, ist "Länge - 3". Mag sein, dass Du
diesen Wert vorab berechnen musst.

Ach ja - als Beispiel solltest Du keinen Text von genau doppelter Länge
nehmen ...

Viele Gruesse!
Helmut
Heike C. Zimmerer
2007-01-27 12:15:18 UTC
Permalink
Post by Ralf Kleemann
Hallo,
$ x=abcdefg
$ echo ${x%???}
abcd


Gruß,

Heike
Ralf Kleemann
2007-01-27 18:13:33 UTC
Permalink
Post by Heike C. Zimmerer
Post by Ralf Kleemann
Hallo,
$ x=abcdefg
$ echo ${x%???}
abcd
welche Funktion hat hier das %-Zeichen?

Gruß Ralf
Heike C. Zimmerer
2007-01-27 18:58:31 UTC
Permalink
Post by Ralf Kleemann
Post by Heike C. Zimmerer
Post by Ralf Kleemann
Hallo,
$ x=abcdefg
$ echo ${x%???}
abcd
welche Funktion hat hier das %-Zeichen?
Es gibt eine ganze Anzahl solcher ${varname<op>string}-Kombinationen;
es lohnt sich, die nachzuschlagen.

${var%pattern} und ${var%%pattern} schneiden die kürzeste bzw. längste
Übereinstimmung mit pattern am Ende von $var ab. Ein Shell-Pattern
'???' wie oben passt auf 3 beliebige Zeichen. ${var%.*} würde
beispielsweise alles ab dem letzten Punkt (also das Suffix)
abschneiden, unabhängig von der Länge.


Gruß,

Heike
Ralf Kleemann
2007-01-27 19:29:14 UTC
Permalink
Post by Heike C. Zimmerer
Es gibt eine ganze Anzahl solcher ${varname<op>string}-Kombinationen;
es lohnt sich, die nachzuschlagen.
wo z.B. kann ich das Nachschlagen?

Gruß Ralf
Daniel Rock
2007-01-27 19:50:30 UTC
Permalink
Post by Ralf Kleemann
Post by Heike C. Zimmerer
Es gibt eine ganze Anzahl solcher ${varname<op>string}-Kombinationen;
es lohnt sich, die nachzuschlagen.
wo z.B. kann ich das Nachschlagen?
http://www.opengroup.org/onlinepubs/009695399/toc.htm

und speziell:

http://www.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html#tag_02_06_02
--
Daniel
Heike C. Zimmerer
2007-01-27 19:54:24 UTC
Permalink
Post by Ralf Kleemann
Post by Heike C. Zimmerer
Es gibt eine ganze Anzahl solcher ${varname<op>string}-Kombinationen;
es lohnt sich, die nachzuschlagen.
wo z.B. kann ich das Nachschlagen?
Auf unixoiden Systemen ist *der* grundlegende Befehl "man". Praktisch
die Mutter aller Befehle, wenn man sich mit der Kommandozeile vertraut
machen möchte ;).

Also erst

man man

um sich damit vertraut zu machen, und dann ein gewagtes

man sh

Gruß,

Heike
Juergen P. Meier
2007-01-28 08:20:16 UTC
Permalink
Post by Ralf Kleemann
Post by Heike C. Zimmerer
Es gibt eine ganze Anzahl solcher ${varname<op>string}-Kombinationen;
es lohnt sich, die nachzuschlagen.
wo z.B. kann ich das Nachschlagen?
man `basename ${SHELL:-sh}`

oder generisch fuer alle Posix-konformen Shells bei http://www.unix.org/
(Link "The Single UNIX Specification Version 3" folgen, kostenfrei
aber Registrierung notwendig. Registrierte Mailaddresse wird nicht bespammt)

Juergen
--
Juergen P. Meier - "This World is about to be Destroyed!"
end
If you think technology can solve your problems you don't understand
technology and you don't understand your problems. (Bruce Schneier)
Ralf Kleemann
2007-01-27 19:38:05 UTC
Permalink
Post by Heike C. Zimmerer
${var%.*} würde
beispielsweise alles ab dem letzten Punkt (also das Suffix)
abschneiden, unabhängig von der Länge.
a="abc.defgh,ts"
echo ${a%???}
abc.defgh

funktioniert nicht
Post by Heike C. Zimmerer
echo ${a%.*}
abc

Gruß Ralf
Ralf Kleemann
2007-01-27 19:39:50 UTC
Permalink
Post by Heike C. Zimmerer
${var%.*} würde
beispielsweise alles ab dem letzten Punkt (also das Suffix)
abschneiden, unabhängig von der Länge.
a="abc.defgh,ts"
echo ${a%???}
abc.defgh

funktioniert nicht
Post by Heike C. Zimmerer
echo ${a%.*}
abc

Gruß Ralf
Loading...