$(<file)(funktioniert auch mit `<file`) ist ein spezieller Operator der Korn-Shell, der von zshund 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 > filewürde a geöffnet und abgeschnitten file), aber dann passiert nichts. So
< file
Öffnet sich filezum Lesen, aber dann passiert nichts, da es keinen Befehl gibt. Also fileist 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 scriptnur 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 ( <fileoder 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, zshführt die $READNULLCMD(einen Pager durch Standard), und , wenn es sowohl Eingangs- und Ausgang Umleitungen, die $NULLCMD( catStandardeinstellung), so dass selbst wenn $(<&3)nicht als die besonderen erkannte Operator, es wird immer noch wie in funktionieren, kshindem ein Pager aufgerufen wird, um dies zu tun (dieser Pager verhält sich so, catda 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 aund b(oder nur , bwenn die multiosOption deaktiviert ist), $(< a > b)würde kopieren azu bund 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 $READNULLCMDgibt $(<&3), $(< a < b)führen Sie die Umleitungen durch, aber erweitern Sie auf nichts.
- Aus irgendeinem Grund wird
bashzwar 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 catwä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 $fileZuordnung 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/mapfileModul und nur für reguläre Dateien), das auch mit Binärdateien funktioniert.
Beachten Sie, dass die pdksh-basierten Varianten von kshim 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.zshbash$(<file)
bashwird das als interpretierencat filename", meinen Sie, dass dieses Verhalten spezifisch für die Befehlssubstitution ist? Denn wenn ich< filenamealleine renne, macht Bash es nicht fertig. Es wird nichts ausgegeben und ich kehre zu einer Eingabeaufforderung zurück.