2016-06-24 12 views
2

Ich versuche, einen Retry-Mechanismus zu implementieren, wenn Sie ein externes Programm mit TCL ausführen. Ich habe Probleme beim Versuch, STDIN dem externen Programm zuzuführen. Ich arbeite jetzt mit einem vereinfachten Beispiel, das versucht, das Problem zu lösen. Nehmen Sie den folgenden Python-Skript (simple.py):TCL - füttern STDIN zu exec

x = raw_input() 
y = raw_input() 
print x + y 

Eingänge 2 Strings aus der Ausgabe werden die Verkettung Ergebnis des Strings sein.

nun folgenden Befehl funktioniert vom TCL-Interpreter:

% exec python stuff.py << 1\n2 
12 

aber wenn ich versuche, es in separaten Befehlen zu spalten, oder sie, bevor Sie diese in eine Zeichenfolge hinzuzufügen, scheitert es.

Ausfallen 1:

% set cmd "python simple.py << 1\n2" 
% exec $cmd 
couldn't execute "python simple.py << 1 
2": no such file or directory 

Ausfallen 2:

% set cmd1 "python simple.py" 
% set cmd2 "1\n2" 
% exec $cmd1 << $cmd2 

konnte nicht ausgeführt werden "Python simple.py": keine solche Datei oder das Verzeichnis

Ausfallen 3:

% set fullCommandString "exec python simple.py << 1\n2" 
% eval $fullCommandString 
Traceback (most recent call last): 
    File "simple.py", line 2, in <module> 
    y = raw_input() 
EOFError: EOF when reading a line 

Der dritte Fall scheint Dadurch wird das Skript gestartet, aber es interpretiert beide Zeilen von STDIN als eins.

Jede Hilfe wird geschätzt.

Antwort

2

Tcl-Befehle interpretieren Whitespaces in ihren Argumenten standardmäßig nicht neu. exec ist einer von diesen, und es folgt den gleichen Regeln. Das bedeutet, dass Sie Tcl anweisen müssen, diese Liste von Wörtern als eine Liste von Wörtern zu interpretieren, da es sonst nur eine Zeichenfolge ist. Zum Glück gibt es dafür {*}; Die Erweiterung Operator Syntax interpretiert den Rest des Wortes als eine Tcl-Liste und verwendet die Wörter aus dieser Liste an dem Punkt, wo Sie es schreiben. Es ist sehr nützlich, finde ich.

Die einfachste Ihr zweiter Fall zu beheben ist eigentlich:

% set cmd1 "python simple.py" 
% set cmd2 "1\n2" 
% exec {*}$cmd1 << $cmd2 

Sie die erste zitierte Tcl-Liste und die dritten durch Hinzufügen fixieren können die 1\n2 ist immer noch als ein einziges Wort interpretiert, um sicherzustellen, (wie sonst Newline a vollkommen vernünftiges Listenelement Trennzeichen).

% set cmd "python simple.py << {1\n2}" 
% exec $cmd 
% set fullCommandString "exec python simple.py << {1\n2}" 
% eval $fullCommandString 

Die dritte wirtschaftlich obwohl geschrieben mehr werden:

% set fullCommandString "exec python simple.py << {1\n2}" 
% {*}$fullCommandString 

Als Faustregel gilt, wenn Sie eval in modernen Tcl (siehe Hinweis: nichtnamespace eval oder interp eval oder uplevel) dann ist es normalerweise ein Hinweis darauf, dass einige Code effizienter gemacht werden könnten und weniger Bugs haben, indem Sie auf exp verwenden Ansion sorgfältig.


tl; dr: Put {*} vor $cmd1 in Ihrem zweiten Beispiel die idiomatische Fix zu erhalten.

Verwandte Themen