Bash: Eval und Echo zusammen verwenden

771
M.O.

Dies ist eine sehr konkrete Frage. Ich habe ein Skript erstellt, das so aussieht, als hätte ich es aus Gründen der Effizienz komplizierter als nötig gemacht. Ist es wirklich effizient? Ich weiß es nicht. Ist es die richtige Schreibweise? Ich weiß es nicht.

Deshalb frage ich diese Frage. Ich möchte wissen, ob der folgende Code verbessert werden kann, wenn er geschrieben wird. Wenn es nicht klar war, dass ich ein Neuling bin, aber mein Skript vervollständigt seinen Zweck.

Dieser Code versucht, die Variablen s$counter= s1, s2, s3, s4...anhand der zuvor definierten Variablen s1$jund s2$jmit jeiner Zeichenfolge zu definieren, die ein Element einer Liste ist (alle zuvor definiert).

counter=1  for j in $ do eval s$counter=$(eval "echo \$s1$j") eval s$((counter+1))=$(eval "echo \$s2$j") counter=$((counter+2)) done 

Es ist verwirrend, aber nackt bei mir. Die innere evalBedeutung $(eval "echo \$s1$j")bedeutet, den Wert von zurückzugeben s1$j. Die zweite evalBedeutung eval s$counter =...soll die Variablen definierens1, s2, s3, s4 ...

So ein Beispiel sei: sagt sie mal für die erste foor Schleife j=adann $(eval "echo \$s1$j") == $s1a, mit dem Wert der s1a zuvor definierte im Skript, zum Beispiel lassen Sie es „sein s1a=10“, so dass, wenn die zweite evalausgewertet wir den Befehl haben, die besagt, „ s1=10“.

Es funktioniert, aber könnte etwas passieren, das dies zu einer möglichen Gedächtnisbedrohung oder so ähnlich macht?

Dieselbe Idee mit dieser Codezeile.

eval $(echo "sed -i '$(eval echo '17i$sed17line')' $file") 

wo sed17lineist was ich hinzufügen möchte in der zeile 17 von file. Es hängt davon ab, wofür ich das Skript verwenden möchte, weshalb ich es als Variable verwende und daher eine Kombination aus echound eval.

Ich habe wieder alles versucht, worüber ich nachdenken konnte, bis das Ergebnis genau das war, was ich wollte.

Ich möchte nur sicherstellen, dass alles korrekt ist und ob es einen Weg gibt, es zu verbessern, wo ich nach diesen Informationen suchen sollte. Vielen Dank!

2
Bash verfügt über ein Array-Konstrukt: http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_10_02.html Normalerweise reicht eine einfache Listenverarbeitung aus. Auch eine Auswertung pro Zeile ist ausreichend. Eval behandelt die erweiterte Zeichenfolge einfach so, als wäre sie im Skript. T Nierath vor 6 Jahren 0
Sie haben Recht! Es ist nur eine Bewertung erforderlich. Vielen Dank! M.O. vor 6 Jahren 0

1 Antwort auf die Frage

1
Kamil Maciorowski

Es ist gut zu wissen, dass es Probleme mit eval( dies und das ) und echo( hier ) gibt. Sie sollten es vermeiden eval, es ist leicht zu missbrauchen.

Auch wenn diese Befehle in Ihren speziellen Fällen hier absolut sicher sind, empfehle ich Ihnen, diese aufzugeben eval. Ihr Code ist dadurch tatsächlich zu kompliziert.


Ihr erstes Beispiel wird mit Arrays viel sauberer. Dies funktioniert in GNU bash 4.4.12 in meinem Debian:

# preparing variables unset -v list s s1 s2 declare -a list=( foo 'X Y' bar baz ) declare -a s declare -A s1=( [foo]='FOO 1' [bar]='BAR 2' [baz]='BAZ beep; eject /dev/sr0' ) declare -A s2=( [foo]='oof oof' [bar]='rab rab' [baz]='zab zab' [X Y]='9')  # your code rewritten, we don't even need a counter for j in "$" do s+=( "$" "$" ) done  # checking contents of s printf '%s\n' "$" 

Hinweis: Suchen Sie nach "indizierten Arrays", "assoziativen Arrays" und deren Verwendung in bash.

Beachten Sie, dass das Element mit Leerzeichen ( X Y) für mich nichts Besonderes ist. aber es würde Ihren Code brechen. Ich kann auch BAZ beep; eject /dev/sr0in meinem haben s1; Ich wage Sie zu setzen s1baz='BAZ beep; eject /dev/sr0', bazin Ihrem listArray haben, Ihren Code ausführen und sehen, was passiert. Das ist, wozu evalfähig ist. Stellen Sie sich jetzt vor, ich stelle rm -rf ~/statt eject ….


Das zweite Beispiel kann stark vereinfacht werden als:

sed -i "17i$sed17line" "$file" 

Sie scheinen eine Vorliebe für eval+ zu haben, echoda Sie eine Vorrichtung geschaffen haben, die sie zweimal verwendet, wenn keine benötigt wird. Vielleicht liegt es daran, dass Ihre Variablen nicht immer auf ihre Werte erweitert werden, wenn Sie dies wünschen. Wenn ja, untersuchen Sie den Unterschied zwischen einfachen ( ') und doppelten Anführungszeichen ( ") in bash.

Ein großes Lob dafür, Zweifel zu haben und die Frage zu stellen.

Vielen Dank! Ich denke, Sie haben mir zu viele Informationen gegeben, die ich verarbeiten konnte, und ich werde vorsichtig sein, wenn ich versuche, alles zu bekommen. Ich würde nicht sagen, dass ich eine Vorurteile habe, ich würde sagen, dass ich kein Wissen habe. Beim Googeln speziell für das, was ich versuchte, alle Antworten zu finden, die ich in Foren wie diesem gefunden hatte, war "eval" und "echo". Vielleicht denke ich, dass die Schritte des Kodex so sein sollten, dass ich zu diesen Antworten führe, aber trotzdem haben sie es getan, sie haben funktioniert und sie haben für mich einen Sinn ergeben. Jetzt versuche ich den Code zu verbessern. M.O. vor 6 Jahren 0
Der Code hat eine sehr spezifische Verwendung, also bin ich nicht besorgt über die falsche Verwendung von "eval", ich sollte es aber wahrscheinlich sein. Würden Sie sagen, eval ist portabel? Ich werde mein Bestes geben, um zu verstehen, was Sie vorgeschlagen haben. M.O. vor 6 Jahren 0
Alles, was naiv Benutzereingaben verwendet und später ausführt (auch wenn es Teil einer größeren Zeichenfolge ist), kann zum Ausführen von beliebigem Code genutzt werden. Dies sollte keine große Rolle spielen, solange das Skript nicht mit Root-Berechtigungen ausgeführt wird. Ein übliches Muster ist auch die Verwendung von var = $ () `der prog als Unterprozess ausführt und seine Ausgabe der Variablen zuordnet. In diesem Fall ist kein "eval" erforderlich. T Nierath vor 6 Jahren 0