2016-06-14 21 views
7
weitergeleitet.

Ich bin auf GNU bash, Version 4.3.11.Mehrzeilige Zeichenfolge mit doppeltem Anführungszeichen löst die Erweiterung des Verlaufs bei nachfolgenden Befehlen mit einem einzelnen Anführungszeichen aus. Es wird an

Angenommen, ich möchte eindeutige Zeilen in einer Datei drucken. Ich bin mit diesem Ansatz, der auch auf eine Datei funktioniert:

$ cat a 
9 
10 
9 
11 
$ awk '!seen[$0]++' a 
9 
10 
11 

Wenn ich jedoch die Eingabe von stdin erhalten, doppelte Anführungszeichen in einem mehrzeiligen und Rohrleitungen zu awk verwenden, ist es nicht:

$ echo "9 
> 10 
> 9 
> 11" | awk '!seen[$0]++' 
bash: !seen[$0]++': event not found 

Das heißt, bash versucht, den Befehl seen zu erweitern, was natürlich nicht bekannt ist, weil es ein Variablenname ist. Aber es sollte nicht passieren, da der Befehl in einfache Anführungszeichen gesetzt wird.

echo ing in einem einfachen Anführungszeichen, Eingang mit mehreren Leitungen funktioniert gut:

$ echo '9 
> 10 
> 9 
> 11' | awk '!seen[$0]++' 
9 
10 
11 

Das Komische ist, dass es funktioniert gut auch auf einem Single-Line-Eingang, die in doppelten Anführungszeichen sind:

$ printf "9\n10\n9\n11" | awk '!seen[$0]++' 
9 
10 
11 

Ich frage mich, warum Bash versucht, Geschichte zu erweitern, wenn es nach einer mutiline Eingabe auftritt, obwohl der Befehl selbst einfache Anführungszeichen verwendet.

Weitere Überlegungen:

ein Rohr zwischen Nachdem es nicht reparieren, entweder:

$ echo "9 
> 10 
> 9 
> 11" | cat - | awk '!seen[$0]++' 
bash: !seen[$0]++': event not found 

Und set +H turns history off Einstellung, so dass es funktioniert gut, weil es nichts zu erweitern nicht versuchen:

$ set +H 
$ echo "9 
> 10 
> 9 
> 11" | awk '!seen[$0]++' 
9 
10 
11 

Ich ging durch die kanonische Antwort von Rici auf how to address error “bash: !d': event not found” in Bash command substitution und fand viele mögliche Gründe, aber keiner entspricht diesem Verhalten.

+1

Es scheint, dass die letzte Zeile als einzelne Zeile geparst wird, anstatt die zuvor in Anführungszeichen eingeschlossene Zeichenfolge einzuschließen. Das bedeutet, dass das '!' So verarbeitet wird, als wäre es in Anführungszeichen gesetzt. Sie werden auch bemerken, dass Sie in der nächsten Zeile ein '>' erhalten, während Sie darauf warten, dass Sie diese wahrgenommene Zeichenfolge schließen. Deshalb funktioniert es auch auf einer einzigen Linie. Sieht nach einem Fehler aus. – 123

+1

Reproduzierbar in 4.2.47. Ich würde einen Fehler einreichen. – choroba

+0

Auch reproduzierbar den ganzen Weg zurück zu '3.2.51' – 123

Antwort

2

Es ist kein Fehler.

Nach der Frage dies in der bash-Bugs Mailing-Liste, bekam ich folgende Antwort:

Geschichte Expansion ist ausdrücklich zeilenorientiert.

Es weiß nichts über den Shell-Zustand, insbesondere den Shell-Quoting-Zustand , der sich über Zeilen erstreckt.

weiß er über vageen schalenartige zitiert, dass über eine große Menge von Unix-Werkzeugen üblich ist - da die Geschichte und die readline Bibliotheken außerhalb der Schale verwendet werden - und dass ein doppeltes Anführungszeichen führt eine Zeichenfolge in Anführungszeichen in welche einfachen Anführungszeichen sind nicht signifikant und hemmen nicht die Geschichte Expansion.

+2

Upvote, um das zu dokumentieren, aber das ist wahnsinniges Verhalten. – tripleee