2016-05-25 6 views
1

Ich musste vorher kein Bash-Skript schreiben. Hier ist was ich tun muss.Verknüpfen der verbleibenden Argumente über das erste N in Bash

Mein Skript wird mit einer Reihe von String-Argumenten ausgeführt. Anzahl der Stiche wird mehr als 8 sein. Ich werde Strings 9 und weiter verketten und daraus eine einzelne Saite machen müssen. So ...

myscript S1 S2 S3 S4 s5 s6 s7 s8 s9 s10 .... (total unbekannt)

im Skript, ich brauche dies zu tun ...

neue Zeichenfolge = s9 + s10 + ...

Ich versuche so etwas ... (aus der Websuche).

array="${@}" 
tLen=${#array[@]} 
# use for loop to read string beyond 9 
for ((i=8; i<${tLen}; i++)); 
do 
    echo ${array[$i]} --> just to show string beyond 9 
done 

Nicht funktioniert. Es wird ausgegeben, wenn i = 0 ist. Hier ist meine Eingabe.

./tastest 1 2 3 4 5 6 7 8 A B C

I A B C erwarte gedruckt werden. Endlich werde ich ABC machen müssen.

Kann jemand helfen?

+1

Weder 'Array = "$ @"' oder 'array = $ {@}' tatsächlich schafft ein Array ; 'Array' ist in beiden Fällen eine Zeichenfolge. Wenn Sie möchten, dass Ihr 'Array' tatsächlich ** ein Array ist, muss es' Array = ("$ @") ' –

Antwort

3

Es sollte viel einfacher als die Schleife in der Frage:

shift 8 
echo "$*" 

Argumente verlieren 1-8; Drucken Sie alle anderen Argumente als eine einzige Zeichenfolge mit einem einzelnen Leerzeichen, das die Argumente trennt (und Leerzeichen innerhalb der Argumente erhalten).

Oder, wenn Sie es in einer Variablen benötigen, dann:

nine_onwards="$*" 

Oder, wenn Sie nicht die ersten 8 Argumente in der Haupt Shell-Prozess wegzuwerfen:

nine_onwards="$(shift 8; echo "$*")" 

können Sie überprüfen Sie, dass es mindestens 9 Argumente gibt, natürlich, beschweren, wenn es nicht gibt. Oder Sie können stattdessen eine leere Zeichenfolge akzeptieren - ohne Fehler.

Und wenn die Argumente müssen (auf die Frage, wie im Änderungsantrag) ohne Leerzeichen verkettet werden, dann müssen Sie mit $IFS jonglieren:

nine_onwards="$(shift 8; IFS=""; echo "$*")" 

Wenn ich die Kommentare von der Interpretation bin Unter dieser Antwort richtig, dann möchten Sie die ersten 8 Argumente in 8 separaten einfachen (Nicht-Array-) Variablen und dann Argumente 9 weiter in einer anderen einfachen Variablen ohne Leerzeichen zwischen den Argumentwerten speichern.

Die trivialen machbar:

var1="$1" 
var2="$2" 
var3="$3" 
var4="$4" 
var5="$5" 
var6="$6" 
var7="$7" 
var8="$8" 
var9="$(shift 8; IFS=""; echo "$*")" 

Die Namen müssen als diejenigen nicht, wie eng verwandt sind. Sie könnten verwenden:

teflon="$1" 
absinthe="$2" 
astronomy="$3" 
lobster="$4" 
darkest_peru="$5" 
mp="$6" 
culinary="$7" 
dogma="$8" 
concatenation="$(shift 8; IFS=""; echo "$*")" 

Sie müssen sie nicht in dieser Reihenfolge tun; Jede Sequenz (Permutation) wird gut funktionieren.

Beachten Sie auch, dass in der Frage, Sie haben:

array="${@}" 

Trotz des Namens, die eine einfache Variable enthalten, die Argumente erzeugt. Um ein Array zu erstellen, müssen Sie Klammern wie diese, wo die Räume sind optional:

array=("[email protected]") 
+0

Vielen Dank. Ich muss auch die ersten 8 in Variablen speichern. 9 und weiter muss in einer anderen Variablen gespeichert werden. – Tas

+3

Bitte aktualisieren Sie Ihre Frage (noch einmal), um zu zeigen, was Sie wirklich wollen. Es gibt wenig frustrierenderes als den Versuch, die Frage "nicht die Frage, die ich wirklich zu stellen versuche" zu beantworten. Du sagst 'Variable'. Meinst du Array, wie deine Frage impliziert? Die Zuweisung 'array =" $ @ "' macht nicht, was Sie denken, dass es tut; es muss 'array = (" $ @ ")' sein, wobei diese Leerzeichen optional sind. –

+0

Sorry für die Verwirrung. Ich muss die ersten 8 in 8 Variablen speichern. 9. und höher sollte zusammengefügt und in einer neuen Variable gespeichert werden. – Tas

-1

Sie sind nah - so etwas wie dies funktionieren würde:

array=(${*}) 
# use for loop to read string beyond 9 
for ((i=8; i<${#array[*]}; i++)); 
do 
    echo -n ${array[$i]} 
done 
+3

Verwenden Sie '" $ @ "' anstelle von "$ {*}". Es gibt massive Unterschiede, wenn das Skript als './testest A 'B C' D E F 'G H I J K 0 1 2' oder so ähnlich aufgerufen wird. –

+0

Zum Beispiel ./testest A 'BC' 'DEF' GHIJK 0 1 2, Mit array = ($ {*}) Ich bekomme IJK012 mit array = "$ *" Ich bekomme nichts, also stehe ich immer noch zu der Antwort, die ich gab , nicht dein Kommentar, der nicht funktioniert! – lostbard

+0

außer du meinst array = ("$ @") – lostbard

1
# Create a 0-index-based copy of the array of input arguments. 
# (You could, however, work with the 1-based pseudo array [email protected] directly.) 
array=("${@}") 

# Print a concatenation of all input arguments starting with the 9th 
# (starting at 0-based index 8), which are passed *individually* to 
# `printf`, due to use of `@` to reference the array [slice] 
# `%s` as the `printf` format then joins the elements with no separator 
# (and no trailing \n). 
printf '%s' "${array[@]:8}" 

# Alternative: Print the elements separated with a space: 
# Note that using `*` instead of `@` causes the array [slice] to be expanded 
# to a *single* string using the first char. in `$IFS` as the separator, 
# which is a space by default; here you could add a trailing \n by using 
# '%s\n' as the `printf` format string. 
printf '%s' "${array[*]:8}" 

Beachten Sie, dass array="${@}" tut nicht Erstellen Sie ein Array - es erstellt einfach einen String-Skalar, der die Verkettung der Elemente des Input-Arrays (unweigerlich) umfasst, die jeweils durch einen Space getrennt sind; Um ein Array zu erstellen, müssen Sie es in (...) einschließen.

Um eine durch Leerzeichen getrennte einzelne Zeichenfolge aus den Argumenten der 9. erstellen in doppelte Anführungszeichen, wie Sie in Ihrem follow-up question beantragen, verwenden Sie die folgende eingeschlossen Start:

printf -v var10 '"%s"' "${array[*]:8}" 

Mit der letzten Probe Anruf von Ihre Frage $var10 enthält dann Literal "A B C", einschließlich die doppelten Anführungszeichen.


Was Argumente 1 bis 8 auf die einzelnen Variablen .:

Jonathan Leffler's helpful answer Zuordnung zeigt, wie die ersten 8 Argumente in einzelnen Variablen zu speichern.

Hier ist eine algorithmische Alternative, die auf einer bestimmten Namen Präfix und Sequenznummer basierend einzelne Variablen erstellt:

n=8 # how many arguments to assign to individual variables 

# Create n 'var<i>' variables capturing the first n arguments. 
i=0 # variable sequence number 
for val in "${array[@]:0:n}"; do 
    declare "var$((++i))=$val" # create $var<i>, starting with index 1 
done 

# Print the variables created and their values, using variable indirection. 
printf "\nvar<i> variables:\n" 
for varName in "${[email protected]}"; do 
    printf '%s\n' "$varName=${!varName}" 
done 
+0

Wenn Sie jedes Element in $ {array [@]: 8} zusammen mit einem Leerzeichen zwischen den Elementen verketten möchten, was müssten Sie tun? – Tas

+0

@Tas: Bitte beachten Sie mein Update, das auch Ihre Folgefrage behandelt. – mklement0

Verwandte Themen