PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : bash: backticks verschachtelt?



McFraggle
02-01-2008, 18:28
Hi!
Mit backticks kann man in der bash ja schön eine subshell starten, was ich zum Beispiel nutze um den Rückgabewert eines Programmes als Aufrufargument für ein Skript zu nutzen.
Nun muss ich jedoch innerhalb der subshell wiederum eine subshell öffnen. Einfaches Verschachteln der Bachticks führt zu Fehlermeldungen.
Was ich versucht habe sieht prinzipiell so aus:

./script `echo "`PROGRAMM` MEHR_FORMEL" | bc`

Ich bekomme eine Fehlermeldung der Art

bash: command substitution: line 1: unexpected EOF while looking for matching `"'
bash: command substitution: line 2: syntax error: unexpected end of file


Wie kann ich nun backticks verschachteln?

rais
02-01-2008, 21:53
Frohes Neues,
keine Ahnung, ob das auch direkt geht, aber warum setzt Du nicht einfach eine Variable dazwischen? So in der Art


x=`PROGRAMM`; ./script `echo "$x MEHR_FORMEL" | bc`

MfG,

peschmae
03-01-2008, 07:49
Das kriegst du hin indem du statt der Backticks
$() verwendest. Das ist schachtelbar.

MfG Peschmä

McFraggle
03-01-2008, 09:50
Danke Euch beiden!
$() wird nun verwendet.
THNX!

ContainerDriver
03-01-2008, 10:56
Du kannst die (geschachtelten) Backticks auch escapen (\`)



echo `echo \`echo \\\`echo \\\\\\\`echo Hallo\\\\\\\`\\\`\``
.

Sieht aber unübersichtlich aus.

McFraggle
03-01-2008, 11:17
:D
Sieht wirklich etwas wirr aus. Aber gut zu wissen...

jan61
03-01-2008, 20:40
:D
Sieht wirklich etwas wirr aus. Aber gut zu wissen...

Ist aber ziemlich logisch, man muss nur richtig zählen ;-) In jeder weiteren Subshell muss der Backtick gegenüber der darüberliegenden Shell entwertet sein, also Backslash. Und den Backslash muss man ab der 2. Ebene auch tarnen, damit er nicht als Entwerter interpretiert wird, also kommen dann immer 2 \ pro Subshell dazu.Man muss einfach mal die Subshells hinabklettern und sich überlegen, was die jeweils amtierende Shell mit den Zeichen macht:

echo H`echo a\`echo l\\\`echo l\\\\\\\`echo o\\\\\\\`\\\`\``
# ich, die Shell führe aus (wenn ich vom Nachkommen die Anwort habe):
# echo H`...`; und nachdem ich fleissig substituiert habe (jedes nach einem
# \ stehende Zeichen nehme ich so, wie es ist und entferne den Entwerter \
# davor), bleibt das innerhalb der Backticks fuer den Sohnemann uebrig:
echo a`echo l\`echo l\\\`echo o\\\`\``
# jetzt bin ich, die erste Subshell dran. Ich muss also ausführen:
# echo a`...` und ich substituiere wie mein Papa. Übrig bleibt fuer den Enkel:
echo l`echo l\`echo o\``
# so, endlich ist die Jugend dran. Ich habe alles von meinen Vorfahren geerbt,
# muss dies hier ausfuehren:
# echo l`...` und der Urenkel kriegt ne leichte Aufgabe:
echo l`echo o`
# ich bin erst in der Grundschule, ich muss nicht mehr substituieren (kann ich
# ja noch gar nicht, kommt erst in der 3. Klasse dran), ich tue:
# echo l`...` und schicke alles zwischen den `` an die Teppichratte:
echo o
# ich liege ja noch in den Windeln (5 Generationen unter einem Dach -
# Donnerwetter!), deshalb muss ich nur mein erstes Wort sprechen, nachdenken
# brauche ich noch nicht:
o
# Manno, der kleine Windelpupser braucht aber! Jetzt hab ich seine Antwort,
# er hat nur ein "o" rausgebracht und ich tue mein Teil dazu mit
# "echo l`echo o`":
lo
# die Kleinen lernen aber auch gar nix mehr heute. Endlich kann ich meinen
# Senf dazugeben, mit "echo l`echo lo`" wird das zu:
llo
# na endlich bin ich wieder dran, ich mache aus "echo a`echo llo`":
allo
# Hach, die Jugend! Wir waren damals nicht so lahm. Nur ich kann sowas:
# aus "echo H`echo allo`" mache ich:
Hallo
Alles klar? :cool:

Jan

EDIT: Um das Ganze rückwärts zu machen, gibt es eine einfache Regel: Jedes für die darüberliegende Shell als Steuerzeichen zu interpretierende Zeichen muss entwertet werden. Im vorliegenden Beispiel musst Du also vor jeden existierenden Backtick und Backslash einen Backslash setzen, wenn Du eine weitere ``-Ebene einziehst. Ich erspare mir mal einen weiteren Generationen-Disput ;-)

ContainerDriver
03-01-2008, 23:27
Hehe, über das Bildungsgesetz habe ich mir vorhin auch Gedanken gemacht ;)
Für die n-te Ebene muss man 2^n - 1 mal den Backslash setzen (Zählung beginnt bei 0).

Du hast es gut erklärt.

McFraggle
04-01-2008, 09:30
Tja, danke für die weiteren Infos! :D
Gibt es eigentlich einen semanischen Unterschied zwischen `xyz` und $(xyz)? Passiert hier genau das Gleiche?

kamome
04-01-2008, 12:41
Meines Wissens identisch

peschmae
05-01-2008, 10:47
Identisch, aber gewisse Shells können das $() afair nicht.

MfG Peschmä

jan61
11-01-2008, 19:29
Meines Wissens identisch

Ein kleiner Hinweis: Die Backtick-Masche funktioniert in jeder Shell, $(...) ist bash-spezifisch.

Jan

peschmae
11-01-2008, 21:42
Ach und falls es einer noch nicht mitbekommen hat - die Backticks sind universell verwendbar, währenddem $() nur mit gewissen shells geht (bash und zsh beispielsweise).

*scnr* und guten Abend allerseits

Peschmä

jan61
12-01-2008, 18:23
Ach und falls es einer noch nicht mitbekommen hat - die Backticks sind universell verwendbar, währenddem $() nur mit gewissen shells geht (bash und zsh beispielsweise).

Sag ich doch ;-)

Jan

@peschmae: Ich habe den Teil nach dem Komma von Deinem Beitrag am 5. 1. tatsächlich überlesen - sorry.

peschmae
13-01-2008, 11:08
Sag ich doch ;-)


Ich doch auch :-)


@peschmae: Ich habe den Teil nach dem Komma von Deinem Beitrag am 5. 1. tatsächlich überlesen - sorry.

Ich dafür den hier *g

MfG Peschmä