Warum erhalte ich eine unerwartete Ausgabe, wenn ich versuche, die vom Benutzer eingegebene Anzahl von Wiederholungen in einer Schleife auszuführen?

Warum erhalte ich eine unerwartete Ausgabe, wenn ich versuche, die vom Benutzer eingegebene Anzahl von Wiederholungen in einer Schleife auszuführen?

Ich schreibe dieses Bash-Shell-Skript:

#!/bin/bash

declare -i N
read N
for i in {1..$N}
do
  echo "Number: $i"
done

(Ich glaube, declare -i Nes ist Neine Ganzzahl)

Beim Ausführen erhalte ich jedoch die folgende Ausgabe:

>vim new.sh
>chmod +x passgen.sh
>./passgen.sh
15
Number: {1..15}

Hier möchte ich dem Benutzer das Limit abnehmen und dann die Schleife ausführen.

Antwort1

Aus man bash:

Die Reihenfolge der Erweiterungen ist: Klammernerweiterung, Tilde-Erweiterung, Parameter- und Variablenerweiterung, arithmetische Erweiterung und Befehlsersetzung (von links nach rechts durchgeführt), Worttrennung und Pfadnamenerweiterung.

Wie Sie sehen, steht die Klammererweiterung zuerst, sie wird also in Ihrem Problem offensichtlich übersprungen. Ich würde stattdessen eine andere Schleife verwenden.

Antwort2

Obwohl das Problem mit der Klammernerweiterung bereits angesprochen wurde, möchte ich nur Folgendes kommentieren:

(Ich glaube, -i N macht aus N eine Ganzzahl.)

Meine Antwort lautet: Ja, das ist der Fall. Und es ist ein Problem, da es eine Schwachstelle bei der Befehlsinjektion darstellt. Wenn dieses Integer-Attribut gesetzt ist, wird der Wert, wenn der Variablen ein Wert zugewiesen wird, als arithmetischer Ausdruck interpretiert.

Wenn der Benutzer a[$(reboot)]diese readEingabeaufforderung eingibt, wird beispielsweise ein Neustartversuch ausgelöst.

Das ist ein allgemeines Problem mit und immer dann bash, wenn arithmetische Ausdrücke ausgewertet werden. Sogar die Verwendung der ksh93-Form (mit oder ohne ) wäre ein Problem, da der Inhalt von immer noch in diesem arithmetischen Kontext ausgewertet wird.zshkshfor (( i = 1; i <= N; i++ ))declare -i NN

for i in {1..$N}wäre (ohne declare -i N) in ksh, zsh oder in Ordnung yash -o braceexpand(würde bei Kauderwelsch eine Schleife bilden, aber keine Befehlszeilen-Schwachstelle einführen), oder Sie können die Standardsyntax verwenden, shvorausgesetzt, Ihre shImplementierung basiert nicht auf ksh.

#! /bin/sh -
IFS= read -r N
i=1; while [ "$i" -lt "$N" ]; do
  printf '%s\n' "Number: $n"
done

kshbehandelt [Operanden von immer noch -ltals arithmetische Ausdrücke und würde daher immer noch Schwachstellen bei der Befehlseinschleusung einführen. Verwenden Sie [[ $i -lt $N ]]oder nicht (( i < N ))in bash/ zsh/ ksh, da dieses Problem ebenfalls auftritt.

Alternativ können Sie awk/ perloder eine beliebige geeignete Programmiersprache verwenden, um die Schleife auszuführen, oder Sie können zunächst die Eingabe bereinigen.

verwandte Informationen