$(<file)
(funktioniert auch mit `<file`
) ist ein spezieller Operator der Korn-Shell, der von zsh
und kopiert wird bash
. Es sieht sehr nach Befehlsersetzung aus, ist es aber nicht wirklich.
In POSIX-Shells lautet ein einfacher Befehl:
< file var1=value1 > file2 cmd 2> file3 args 3> file4
Alle Teile sind optional. Sie können nur Umleitungen, nur Befehle, nur Zuweisungen oder Kombinationen verwenden.
Wenn es Umleitungen, aber keinen Befehl gibt, werden die Umleitungen ausgeführt (also > file
würde a geöffnet und abgeschnitten file
), aber dann passiert nichts. So
< file
Öffnet sich file
zum Lesen, aber dann passiert nichts, da es keinen Befehl gibt. Also file
ist das dann geschlossen und das wars. Wenn $(< file)
es sich um eine einfache Befehlsersetzung handelt , wird sie zu nichts erweitert.
In der POSIX-Spezifikation führt in $(script)
, wenn es script
nur aus Umleitungen besteht, zu nicht spezifizierten Ergebnissen . Das soll das besondere Verhalten der Kornschale ermöglichen.
In ksh (hier getestet mit ksh93u+
), wenn das Skript aus einem und nur einem einfachen Befehl besteht (obwohl Kommentare vorher und nachher zulässig sind), der nur aus Umleitungen besteht (kein Befehl, keine Zuweisung) und wenn die erste Umleitung ein stdin (fd) ist 0) einspeisen ( <
, <<
oder <<<
) die Umleitung, so:
$(< file)
$(0< file)
$(<&3)
(auch $(0>&3)
eigentlich da das eigentlich der gleiche Operator ist)
$(< file > foo 2> $(whatever))
aber nicht:
$(> foo < file)
- Noch
$(0<> file)
- Noch
$(< file; sleep 1)
- Noch
$(< file; < file2)
dann
- Alle außer der ersten Umleitung werden ignoriert (sie werden analysiert).
- und es erweitert sich auf den Inhalt der Datei / heredoc / herestring (oder was auch immer aus dem Dateideskriptor gelesen werden kann, wenn Dinge wie verwendet werden
<&3
) abzüglich der nachfolgenden Zeilenumbruchzeichen.
als ob mit $(cat < file)
außer dem
- Das Lesen erfolgt intern durch die Shell und nicht durch
cat
- Es ist weder ein Rohr noch ein zusätzlicher Prozess erforderlich
- Infolgedessen bleibt jede Änderung danach (wie in
$(<${file=foo.txt})
oder $(<file$((++n)))
) , da der darin enthaltene Code nicht in einer Unterschale ausgeführt wird.
- Lesefehler (jedoch keine Fehler beim Öffnen von Dateien oder beim Duplizieren von Dateideskriptoren) werden unbemerkt ignoriert.
In zsh
, ist es die gleiche , außer dass das spezielle Verhalten nur dann ausgelöst wird , wenn gibt es nur eine Datei - Eingabe - Umleitung ( <file
oder 0< file
, nein <&3
, <<<here
, < a < b
...)
Außer beim Emulieren anderer Shells in:
< file
<&3
<<< here...
Das ist , wenn es nur Eingang Umleitungen ohne Befehle ist, außerhalb des Befehls Substitution, zsh
führt die $READNULLCMD
(einen Pager durch Standard), und , wenn es sowohl Eingangs- und Ausgang Umleitungen, die $NULLCMD
( cat
Standardeinstellung), so dass selbst wenn $(<&3)
nicht als die besonderen erkannte Operator, es wird immer noch wie in funktionieren, ksh
indem ein Pager aufgerufen wird, um dies zu tun (dieser Pager verhält sich so, cat
da sein Standard eine Pipe ist).
Doch während ksh
‚s $(< a < b)
auf den Inhalt erweitern würde a
, in zsh
, dehnt es sich auf den Inhalt a
und b
(oder nur , b
wenn die multios
Option deaktiviert ist), $(< a > b)
würde kopieren a
zu b
und erweitern , um nichts, usw.
bash
hat einen ähnlichen Operator, aber mit ein paar Unterschieden:
Kommentare sind vorher erlaubt, aber nicht danach:
echo "$(
# getting the content of file
< file)"
funktioniert aber:
echo "$(< file
# getting the content of file
)"
dehnt sich zu nichts aus.
Wie in zsh
, nur eine Datei stdin Umleitung, obwohl es kein Zurückgreifen auf a $READNULLCMD
gibt $(<&3)
, $(< a < b)
führen Sie die Umleitungen durch, aber erweitern Sie auf nichts.
- Aus irgendeinem Grund wird
bash
zwar nicht aufgerufen cat
, aber dennoch ein Prozess gegabelt, der den Inhalt der Datei durch eine Pipe führt, wodurch die Optimierung wesentlich geringer ist als in anderen Shells. Es ist in der Tat wie ein $(cat < file)
Wo cat
wäre ein eingebautes cat
.
- Infolgedessen gehen alle darin vorgenommenen Änderungen nachträglich verloren (in den
$(<${file=foo.txt})
oben genannten Fällen geht beispielsweise diese $file
Zuordnung nachträglich verloren).
In bash
, IFS= read -rd '' var < file
(funktioniert auch in zsh
) ist eine effektivere Methode, um den Inhalt einer Textdatei in eine Variable einzulesen . Es hat auch den Vorteil, dass die nachgestellten Zeilenumbrüche beibehalten werden. Siehe auch $mapfile[file]
in zsh
(im zsh/mapfile
Modul und nur für reguläre Dateien), das auch mit Binärdateien funktioniert.
Beachten Sie, dass die pdksh-basierten Varianten von ksh
im Vergleich zu ksh93 einige Variationen aufweisen. Von Interesse in mksh
(einer dieser von pdksh abgeleiteten Muscheln), in
var=$(<<'EOF'
That's multi-line
test with *all* sorts of "special"
characters
EOF
)
wird dahingehend optimiert, dass der Inhalt des hier vorliegenden Dokuments (ohne die nachgestellten Zeichen) erweitert wird, ohne dass eine temporäre Datei oder Pipe verwendet wird, wie dies sonst bei den hier verwendeten Dokumenten der Fall ist, was es zu einer effektiven mehrzeiligen Anführungszeichen-Syntax macht.
Für alle Versionen von und portierbar zu sein ksh
, bedeutet , sich darauf zu beschränken, nur Kommentare zu vermeiden und zu berücksichtigen, dass Änderungen an Variablen, die innerhalb von vorgenommen wurden, beibehalten werden können oder nicht.zsh
bash
$(<file)
bash
wird das als interpretierencat filename
", meinen Sie, dass dieses Verhalten spezifisch für die Befehlssubstitution ist? Denn wenn ich< filename
alleine renne, macht Bash es nicht fertig. Es wird nichts ausgegeben und ich kehre zu einer Eingabeaufforderung zurück.