'\ n' in 'IFS = $' \ n 'ist eine Variable?

12

Ich stelle fest, dass Newline IFSmit einem $ als Präfix gesetzt werden sollte

IFS=$'\n'

aber wenn ein Doppelpunkt gesetzt ist, einfach

IFS=:

Ist \neine Variable?

Infinitesimalrechnung
quelle

Antworten:

21

Dass $'...'in bashnicht Parametern Expansion ist, es ist eine besondere Art von Zitat eingeführt , ksh93dass erweitert diejenigen \n, \x0a, \12Codes zu einem Newline - Zeichen. zshauch hinzugefügt \u000a. ksh93und bashauch \cjwährend zshhat \C-J. ksh93unterstützt auch Variationen wie \x{a}.

Der $ist ein Hinweis , dass es irgendeine Form oder Expansion. Aber in jedem Fall, Sie unterscheidet sich von den anderen Formen von Erweiterungen, die Verwendung $(wie $((1 + 1)), $paramoder $(cmd)), dass sie nicht in doppelte Anführungszeichen oder hier Dokumente (durchgeführt echo "$'x'"Ausgänge $'x'in allen Schalen obwohl nicht spezifiziert ist pro POSIX) und seine Expansion ist nicht Gegenstand der Spaltung + glob, es ist definitiv näher an einem Quotierungsoperator als an einem Expansionsoperator.

IFS=\nwürde IFS auf setzen n( \wird als Anführungszeichen behandelt) und IFS="\n"oder IFS='\n'würde IFS auf die beiden Zeichen Backslash und setzen n.

Sie können auch verwenden:

IFS='
'

oder

IFS="
"

oder

IFS=$'
'

Um eine wörtliche Newline geben, obwohl das weniger lesbar (und man kann nicht anders sehen als die Dinge mit wie set listin , viob $IFSenthält anderes Abstand Zeichen in diesem Code).

IFS=:, IFS=':', IFS=":", IFS=$':'Alle Set IFS zu , :so dass es keine Rolle spielt , die Sie verwenden.

$'...'(mit Variationen) unterstützt wird , indem mindestens: ksh93, zsh, bash, mksh, busybox sh, FreeBSD sh. ksh93und bashhat auch eine $"..."Form von Zitaten für die Lokalisierung von Text verwendet , obwohl es selten , wie es ist umständlich verwendet wird zu implementieren und portabel und zuverlässig zu nutzen.

Die esund fishShells können auch \naußerhalb von Anführungszeichen verwendet werden, um zu Newline zu erweitern.

Einige Tools mögen printf, einige Implementierungen von echooder awkkönnen diese auch \nselbst erweitern. Zum Beispiel kann man tun:

printf '\n'
awk 'BEGIN{printf "\n"}'
echo
echo '\n\c' # UNIX compliant echos only

zur Ausgabe des Zeilenumbruchs, beachten Sie jedoch Folgendes:

IFS = $ (printf '\ n')

funktioniert nicht, da durch die Befehlsersetzung ( $(...)) alle nachgestellten Zeilenumbrüche entfernt werden. Sie können jedoch verwenden:

eval "$(printf 'IFS="\n"')"

Was funktioniert, weil die Ausgabe von printfin einem "Zeichen endet , nicht in einem Zeilenumbruch.

Der Vollständigkeit halber ist in der rcShell und den Derivaten (wie esoder akanga) $'\n'tatsächlich die Erweiterung dieser \nVariablen (eine Variable, deren Name die Folge von zwei Zeichen \und ist n). Diese Schalen haben keine Beschränkung auf , welche Zeichen Variablennamen enthalten kann , und haben nur eine Art von Anführungszeichen: '...'.

$ rc
; '\n' = (foo bar)
; echo $'\n'
foo bar
; echo $'\n'(1)
foo

rcVariablen werden ebenfalls alle in die Umgebung exportiert, aber zumindest in der Unix-Variante von rc, für Variablennamen wie \n, wird die Umgebungsvariablenversion einer Form der Codierung unterzogen:

; env | grep foo | sed -n l
__5cn=foo\001bar$

( Dies 0x5cist der Bytewert von ASCII \; siehe auch, wie diese Arrayvariable mit einem 0x1-Byte als Trennzeichen codiert wurde).

Stéphane Chazelas
quelle
1
+1für den üblichen unmenschlichen Wissensstand
Steven Penny
10

Dies ist ANSI-C-Zitat :

Formularbegriffe $'string'werden gesondert behandelt. Das Wort wird zu erweitert string, wobei mit einem umgekehrten Schrägstrich versehene Zeichen gemäß dem ANSI C-Standard ersetzt werden.

Somit $'\n'wird durch eine neue Zeile ersetzt.

Dies hat nichts mit der Erweiterung der Shell-Parameter zu tun , obwohl $.

Stephen Kitt
quelle
6

Strings wie $'\n'wurden ksh93von POSIX eingeführt und sind derzeit nicht Bestandteil des POSIX-Standards.

Sie ermöglichen die Verwendung der meisten C-ähnlichen Escapes, z. B. $'\u2345'und der Escapes, die auch von unterstützt werden echo.

Beachten Sie, dass Sie Folgendes verwenden können, wenn Sie diese Escape-Methode nicht verwenden möchten (im Fall von ksh93 oder bash):

IFS='
'

Das ist äquivalent, aber schwerer zu lesen.

Übrigens: Diese Erweiterung hat das POSIX-Standardkomitee bereits bestanden, es ist jedoch für SUSv8 geplant , das voraussichtlich nicht vor dem Jahr 2020 erscheinen wird, da wir zuerst an unserer Verzögerung hinter der aktuellen Liste der Fehler arbeiten müssen.

schily
quelle
Die $'...'Erweiterungen unterscheiden sich von denen von echo. Sie ähneln eher denen für das Formatargument von printf. Für echowird eine 0 in \0123while für $'...'und printfformat benötigt, \0123wäre \012eine neue Zeile gefolgt von einem Wurf 3.
Stéphane Chazelas
1
Beachten Sie, dass die $'...'Spezifikation noch diskutiert wird. Mit dem derzeit vorgeschlagenen Wortlaut sind noch einige Probleme zu lösen.
Stéphane Chazelas
IIRC, Es wurde geschlossen, aber wiedereröffnet. Da es noch viel Zeit gibt, bis es in Kraft tritt, sehe ich kein wirkliches Problem damit.
Schily
1
Es wurde geschlossen, ich habe einige Einwände erhoben, es wurde wiedereröffnet, es wurde dann geändert, es gibt immer noch einige Probleme (die meisten betreffen die \uxxxxErweiterung) und es ist keine Lösung in Sicht, die bestehende Implementierungen berücksichtigen würde. Es wird also möglicherweise nicht in die nächste POSIX-Version aufgenommen. Vielleicht könnten sie die \uxxxxErweiterung für Ausgabe 8 auslassen, so dass wir zumindest noch haben können $'\n'.
Stéphane Chazelas