schlonz
Anmeldungsdatum: 30. November 2005
Beiträge: 294
Wohnort: berlin
|
Mein Skript soll eine Reihe von Argumenten übernehmen können, wobei erstes bis vorletztes Argument Quelldateien sein sollen, das letzte Argument dann ist die Zieldatei. Ich suche also nach einem eleganten weg um $@ in zwei Variablen aufzuspalten: $quellen enthält den Substring einschliesslich bis zum vorletzten Token $ziel enthält nur das letzte Token Ich könnte in einer Schleife alles mit shift auseinandernehmen und wieder zusammensetzen, aber es gibt bestimmt einen schöneren Weg dafür? Die Bash hat ja einiges an Stringmanipulationsmöglichkeiten an Bord..
|
MrKanister
Anmeldungsdatum: 13. Oktober 2007
Beiträge: 2105
|
Schlagt mich von mir aus für die Komplexität...aber ich mag's 😀 :
#!/bin/bash
argumente_bis_zum_vorletzten=$(eval eval echo \\\${1..$(($# - 1))})
letztes_argument=${!#}
echo $argumente_bis_zum_vorletzten
echo $letztes_argument Es gibt bestimmt noch einen schöneren Weg, aber einen schnelleren bestimmt nicht;) martin@martin-desktop:~$ example2 1 2 3 4 5
1 2 3 4
5 Gruß Martin
|
audax
Anmeldungsdatum: 15. September 2006
Beiträge: 1253
|
Öhm...in der Bash bekomme ich es auch grad nicht hin... So jedenfalls in der Zsh:
#!/bin/zsh
echo ${@[-1]} # letztes Argument
echo ${@[0,-2]} # alle bis auf das Letzte
|
MrKanister
Anmeldungsdatum: 13. Oktober 2007
Beiträge: 2105
|
Darf ich bei dieser Gelegenheit erwähnen, dass ich langsam anfange die Zsh exorbitant geil zu finden 😲
|
MrKanister
Anmeldungsdatum: 13. Oktober 2007
Beiträge: 2105
|
Hier vielleicht noch eine Variante für Normalsterbliche, die zu faul sind, sich die Zsh zu installieren 😀
argumente_bis_zum_vorletzten=""
for i in $(seq $(($# - 1)))
do
argumente_bis_zum_vorletzten=$(echo $argumente_bis_zum_vorletzten ${!i})
done
letztes_argument=${!#}
echo $argumente_bis_zum_vorletzten
echo $letztes_argument Die Zeile
argumente_bis_zum_vorletzten="" kann man auch weglassen, wenn man auf "unbound variable" steht 😉
|
audax
Anmeldungsdatum: 15. September 2006
Beiträge: 1253
|
Und so ginge es ordentlich 😉
#!/bin/bash
declare -a sources
i=0
until [[ -z $2 ]]
do
sources[i]=$1
shift
i=$((i+1))
done
echo $@ # letztes argument
echo ${sources[*]} # rest Bäh, Bash stinkt 😉
|
MrKanister
Anmeldungsdatum: 13. Oktober 2007
Beiträge: 2105
|
audax hat geschrieben: Bäh, Bash stinkt 😉
Wie wäre es zur Abwechselung mal mit einem Bash-Bashing ?
|
audax
Anmeldungsdatum: 15. September 2006
Beiträge: 1253
|
Abwechslung? Eigentlich ist das bei mir die Regel 😉 Btw, ich hatte eine Unschönheit:
#!/bin/bash
declare -a sources
i=0
until [[ -z $2 ]]
do
sources[i]=$1
shift
let "i++"
done
echo $@
echo ${sources[*]} Trotzdem bäh.
|
schlonz
(Themenstarter)
Anmeldungsdatum: 30. November 2005
Beiträge: 294
Wohnort: berlin
|
Schönen Dank für die Hilfe. Ich hab ein paar Minuten vor der ersten Antwort selber auch eine Lösung via Array gefunden, ist aber mit vier Zeilen inakzeptabel aufwendig und kömmt nicht an Eure Zweizeiler ran ☺ Wobei ich gestehen muß, daß ich die Zeile mit dem eval eval nicht so ganz verstehe. Um mich mal der Code-Parade anzuschließen: Via Array:
#!/bin/bash
args=($@)
let lastIndex=${#args[*]}-1
targetFile=${args[lastIndex]}
args[lastIndex]=""
echo $targetFile
echo ${args[*]}
P.S.: Ich hab mich ja bisher gesträubt, aber vielleicht muß ich mir doch mal die Zsh näher anschauen ♥
|
audax
Anmeldungsdatum: 15. September 2006
Beiträge: 1253
|
Ah...$@ ist in der Bash also kein echtes Array! Diese Shell ist dermaßen inkonsistent.. /o
|
MrKanister
Anmeldungsdatum: 13. Oktober 2007
Beiträge: 2105
|
schlonz hat geschrieben: Wobei ich gestehen muß, daß ich die Zeile mit dem eval eval nicht so ganz verstehe.
Mit einem eval wird der Code 2x ausgeführt. Mit 2 eval's wird der Code 3x ausgeführt... Bei einem Beispiel von 5 Argumenten: Aus
\\\${1..$(($# - 1))} wird
\${1..4} wird
$1 $2 $3 $4 . Das ist alles 😉
|
audax
Anmeldungsdatum: 15. September 2006
Beiträge: 1253
|
Klappt aber leider nicht mit 10 oder mehr Argumenten 😉
|
MrKanister
Anmeldungsdatum: 13. Oktober 2007
Beiträge: 2105
|
Komischerweise tut es das doch...wobei ich mich im Moment Frage warum 😲
#!/bin/bash
argumente_bis_zum_vorletzten=$(eval eval echo \\\${1..$(($# - 1))})
letztes_argument=${!#}
echo $argumente_bis_zum_vorletzten
echo $letztes_argument martin@martin-desktop:~$ example2 1 2 3 4 5 6 7 8 9 10 11 12 13 14
1 2 3 4 5 6 7 8 9 10 11 12 13
14 EDIT: Oh...
martin@martin-desktop:~$ example2 1 2 3 4 5 6 7 8 9 foo bar
1 2 3 4 5 6 7 8 9 10
bar
|
MrKanister
Anmeldungsdatum: 13. Oktober 2007
Beiträge: 2105
|
Ok...dann ergänzen wir die ohne hin schon verstümmelte Zeile eben ein wenig 😉
#!/bin/bash
argumente_bis_zum_vorletzten=$(eval eval echo \\\$\{{1..$(($# - 1))}\})
letztes_argument=${!#}
echo $argumente_bis_zum_vorletzten
echo $letztes_argument martin@martin-desktop:~$ example2 1 2 3 4 5 6 7 8 9 foo bar
1 2 3 4 5 6 7 8 9 foo
bar
|
schlonz
(Themenstarter)
Anmeldungsdatum: 30. November 2005
Beiträge: 294
Wohnort: berlin
|
Mr. Kanister hat geschrieben:
Das ist alles 😉
Ok.. so langsam versteh ich's ☺ Trickreich! audax hat geschrieben: Ah...$@ ist in der Bash also kein echtes Array! Diese Shell ist dermaßen inkonsistent.. /o\\
Yo.. wenn ich's richtig verstanden hab, dann ist $@ ein String. Ist aber im nu in ein Array umgewandelt ☺ Inkosistent hin oder her, was mich an Bash am meisten stört, ist das es außer dem Quellcode nirgends ein Dokument zu geben scheint, das einfach mal alle Features zum Nachschlagen auflistet. Alles muß man sich aus Tutorials zusammenklauben.
|