'\ n' w `IFS = $ '\ n' jest zmienną?

12

Zauważam, że aby ustawić IFSnową linię, należy użyć prefiksu $

IFS=$'\n'

ale po prostu ustaw dwukropek

IFS=:

Czy \njest zmienną?

Rachunek różniczkowy
źródło

Odpowiedzi:

21

Że $'...'w bashnie jest parametr ekspansji, to szczególny rodzaj środki wprowadzone przez ksh93które rozszerza te \n, \x0a, \12kody do znaku nowej linii. zshrównież dodane \u000a. ksh93a bashtakże \cj, gdy zshma \C-J. ksh93obsługuje również odmiany takie jak \x{a}.

$Jest sygnałem, że niektóre formy lub ekspansję. Ale w każdym razie, że różni się od innych form ekspansji że stosowanie $(jak $((1 + 1)), $paramlub $(cmd)) tym, że nie jest wykonywana wewnątrz cudzysłowach lub tutaj dokumenty ( echo "$'x'"wyjścia $'x'we wszystkich muszli choć jest nieokreślony za POSIX) i jego ekspansja nie podlega ułamku + glob, jest zdecydowanie bliższy operatorowi cytowania niż operatorowi ekspansji.

IFS=\nstworzyłaby FI, n( \jest traktowany jako operator cytowanie) i IFS="\n"czy IFS='\n'będzie ustawiony IFS na dwie kreski ułamkowe odwrócone i n.

Możesz także użyć:

IFS='
'

lub

IFS="
"

lub

IFS=$'
'

Aby przejść do dosłownego przełamane, choć to mniej czytelne (i nie można zobaczyć inny niż przy użyciu rzeczy jak set listw viczy $IFSzawiera inne znaki odstępów w tym kodzie).

IFS=:, IFS=':', IFS=":", IFS=$':'Wszystkie zestaw do IFS :, więc nie ma znaczenia, który używasz.

$'...'wspiera (z odmian) przez co najmniej: ksh93, zsh, bash, mksh, Busybox sh, FreeBSD sh. ksh93a bashtakże mają $"..."formę cudzysłowów używanych do lokalizacji tekstu, chociaż jest rzadko używany, ponieważ jest trudny do wdrożenia i użycia przenośnego i niezawodnego.

Te esi fishmuszle mogą również korzystać \npoza cytatami rozszerzyć do nowej linii.

Niektóre narzędzia, takie jak printfniektóre implementacje echolub same awkmogą je rozszerzyć \n. Na przykład można zrobić:

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

do wyjścia znaku nowej linii, ale pamiętaj, że:

IFS = $ (printf '\ n')

nie będzie działać, ponieważ polecenie podstawienie ( $(...)) usuwa wszystkie końcowe znaki nowego wiersza. Możesz jednak użyć:

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

Który działa, ponieważ wyjście printfkończy się "znakiem, a nie znakiem nowej linii.

Teraz, dla kompletności, w rcpowłoce i pochodnych (takich jak eslub akanga), $'\n'rzeczywiście jest rozwinięciem tej \nzmiennej (zmiennej, której nazwa jest ciągiem dwóch znaków \i n). Pociski te nie mają ograniczeń co nazwy zmiennych znaków i może zawierać tylko jeden rodzaj cytatów: '...'.

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

rcwszystkie zmienne są również eksportowane do środowiska, ale przynajmniej w wariancie uniksowym rc, w przypadku nazw zmiennych takich jak \nwersja zmiennej środowiskowej jest poddawana kodowaniu:

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

( 0x5cbędąca wartością bajtu ASCII \; zobacz także, jak ta zmienna tablicowa została zakodowana bajtem 0x1 jako separatorem).

Stéphane Chazelas
źródło
1
+1dla zwykłego nieludzkiego poziomu wiedzy
Steven Penny
10

To jest cytowanie ANSI-C :

Słowa formularza $'string'są traktowane specjalnie. Słowo rozwija się do string, z zastąpionymi znakami odwrotnego ukośnika zgodnie z normą ANSI C.

W $'\n'ten sposób zostaje zastąpiony nowym wierszem.

Nie ma to związku z rozszerzaniem parametrów powłoki , pomimo użycia $.

Stephen Kitt
źródło
6

Ciągi takie $'\n'zostały wprowadzone ksh93i obecnie nie są częścią standardu POSIX.

Pozwalają na użycie większości ucieczek typu C, np. $'\u2345'I takich, które również są obsługiwane echo.

Zauważ, że jeśli nie podoba ci się (w przypadku ksh93 lub bash) korzystanie z tej metody ucieczki, nadal możesz użyć:

IFS='
'

co jest równoważne, ale trudniejsze do odczytania.

BTW: To rozszerzenie już przekroczyło standardowy komitet POSIX, ale jest zaplanowane na SUSv8, który ma pojawić się nie wcześniej niż w 2020 roku, ponieważ najpierw musimy popracować nad opóźnieniem w stosunku do bieżącej listy błędów.

schily
źródło
Te $'...'rozszerzenia różni się od echo. Są bardziej podobne do argumentów formatu printf. For echo, 0 jest wymagane w \0123while for $'...'i printfformacie, \0123byłby \012nowy wiersz, a następnie
litera
1
Zauważ, że $'...'specyfikacja jest wciąż dyskutowana. Obecnie proponowane sformułowanie wymaga rozwiązania.
Stéphane Chazelas
IIRC, został zamknięty, ale został ponownie otwarty. Z uwagi na fakt, że jest jeszcze dużo czasu, zanim zacznie działać, nie widzę w tym prawdziwego problemu.
schily
1
Został zamknięty, zgłosiłem kilka zastrzeżeń, został ponownie otwarty, następnie został poprawiony, nadal istnieje kilka problemów (większość z nich dotyczy \uxxxxrozszerzenia) i brak widocznej rozdzielczości, która uwzględniałaby istniejące wdrożenia. Dlatego może nie przejść do następnej wersji POSIX. Może mogliby pominąć \uxxxxrozszerzenie dla wydania 8, abyśmy mogli przynajmniej mieć $'\n'.
Stéphane Chazelas