Jak nazywa się składnia str=$'Hello World\n===========\n'? zmienne podstawienie?
zengr,
5
@zengr: Nazywa się to cytowaniem ANSI-C , jest także obsługiwane w zshi ksh; jednak NIE jest zgodny z POSIX.
mklement0
4
@ mkelement0, pochodzi z ksh93, jest także obsługiwany przez zsh, bash, mksh i FreeBSD sh, a jego włączenie do kolejnej ważnej wersji POSIX jest dyskutowane
Stéphane Chazelas
1
Wydaje się, że nie działa z podwójnymi cudzysłowami? na przykład str=$"My $PET eats:\n$PET food"? To podejście działa w przypadku podwójnych cytatów
Brad Parks
31
Możesz wstawić dosłowne znaki nowej linii w pojedynczych cudzysłowach (w dowolnej powłoce w stylu Bourne / POSIX).
str='Hello World
===========
'
W przypadku ciągu wielowierszowego dokumenty tutaj są często wygodne. Ciąg jest podawany jako dane wejściowe do polecenia.
mycommand <<'EOF'HelloWorld===========
EOF
Jeśli chcesz zapisać ciąg w zmiennej, użyj catpolecenia w podstawieniu polecenia. Znaki nowego wiersza na końcu ciągu zostaną usunięte przez podstawienie polecenia. Jeśli chcesz zachować ostatnie znaki nowej linii, umieść korek na końcu i zdejmij go później. W powłokach zgodnych z POSIX możesz pisać, str=$(cat <<'EOF'); str=${str%a}a następnie heredoc właściwy, ale bash wymaga, aby heredoc pojawił się przed nawiasem zamykającym.
str=$(cat <<'EOF'HelloWorld===========
a
EOF); str=${str%a}
W ksh, bash i zsh możesz użyć $'…'cytowanego formularza, aby rozwinąć znaki odwrotnego ukośnika w cudzysłowach.
Korzystam z GNU bash 4.1.5 i str=$(cat <<'EOF')nie działa tak, jak jest. )Musi zostać umieszczony w następnym wierszu po końcu dokumentu EOF... ale mimo to traci końcowy znak nowej linii z powodu polecenia Podstawienie.
Peter.O
@fred Dobre punkty, wyjaśniłem o końcowych znakach nowej linii i pokazałem kod, który działa w bash. Myślę, że to błąd w bashu, choć szczerze mówiąc po ponownym przeczytaniu specyfikacji POSIX, nie jest jasne, czy zachowanie jest wymagane, gdy << znajduje się w podstawieniu polecenia, a heredoc nie.
Gilles
Świetna sprawa; aby zachować końcowe (i wiodące) \ninstancje bashpodczas przechwytywania dokumentu tutaj w zmiennej, rozważ IFS= read -r -d '' str <<'EOF'...jako alternatywę dla podejścia ograniczającego (patrz moja odpowiedź).
BTW. Nie potrzebujesz końcowego \ n, ponieważ echoautomatycznie doda jeden, chyba że podasz -n. (Jednak głównym celem pytania jest to, jak przekształcić te nowe wiersze w zmienną).
Peter.O
+1 Ze wszystkich rozwiązań, to jest najbardziej bezpośrednie i najprostsze.
Hai Vu,
echo -e nie działa w systemie OS X
Greg M. Krsak
2
@GregKrsak: W bash, echo -eczyni pracę na OS X - to dlatego, że echojest bash wbudowane (zamiast zewnętrznego wykonywalny) i że wbudowane obsługuje -e. (Jako wbudowany, powinien działać na wszystkich platformach, na których działa bash; nawiasem mówiąc, echo -edziała kshi zshrównież). Jednak zewnętrzne echonarzędzie w systemie OS X - /bin/echo- rzeczywiście nie obsługuje -e.
mklement0
3
Jeśli wiele razy potrzebujesz nowego wiersza w skrypcie, możesz zadeklarować zmienną globalną zawierającą nowy wiersz. W ten sposób możesz używać go w ciągach cudzysłowów (zmienne rozszerzenia).
NL=$'\n'
str="Hello World${NL} and here is a variable $PATH ===========${NL}"
Jeśli używasz bashi wolisz używać rzeczywistych znaków nowej linii dla czytelności , readto kolejna opcja przechwytywania dokumentu tutaj w zmiennej , która (podobnie jak inne rozwiązania tutaj) nie wymaga użycia podpowłoki.
# Reads a here-doc, trimming leading and trailing whitespace.# Use `IFS= read ...` to preserve it (the trailing \n, here).
read -r -d '' str <<'EOF'# Use `IFS= read ...` to preserve the trailing \nHelloWorld===========
EOF
# Test: output the variable enclosed in "[...]", to show the value's boundaries.
$ echo "$str"[HelloWorld===========]
-rzapewnia, że readnie interpretuje danych wejściowych (domyślnie traktowałby ukośniki specjalne, ale jest to rzadko potrzebne).
-d ''ustawia separator „rekordu” na pusty ciąg, powodując readodczytanie całego wejścia naraz (zamiast tylko jednej linii).
Zauważ, że pozostawiając $IFS(wewnętrzny separator pól) na wartości domyślnej $' \t\n'(spację, tabulator, nową linię), wszelkie początkowe i końcowe białe znaki są przycinane od wartości przypisanej do $str, w tym nowej linii tutaj-doc.
(Zauważ, że chociaż treść tutaj-doc zaczyna się od linii po ograniczniku początkowym ( 'EOF'tutaj), nie zawiera wiodącej nowej linii).
Zwykle jest to pożądane zachowanie, ale jeśli chcesz tę końcową linię, użyj IFS= read -r -d ''zamiast po prostu read -r -d '', ale zwróć uwagę, że wszystkie początkowe i końcowe białe znaki są następnie zachowywane.
(Należy pamiętać, że przejście IFS= bezpośrednio do readpolecenia oznacza, że przypisanie działa tylko podczas tego polecenia, więc nie ma potrzeby przywracania poprzedniej wartości).
Użycie dokumentu tutaj pozwala również opcjonalnie użyć wcięcia w celu uruchomienia ciągu wielowierszowego dla zapewnienia czytelności:
# Caveat: indentation must be actual *tab* characters - spaces won't work.
read -r -d '' str <<-'EOF'# NOTE: Only works if the indentation uses actual tab (\t) chars.HelloWorld===========
EOF
# Output the variable enclosed in "[...]", to show the value's boundaries.# Note how the leading tabs were stripped.
$ echo "$str"[HelloWorld===========]
Umieszczenie -między znakiem <<otwierającym doc tutaj i otwierającym ( 'EOF'tutaj) powoduje, że wiodące znaki tabulacji są usuwane z ciała doc doc, a nawet ogranicznika zamykającego, ale należy pamiętać, że działa to tylko z rzeczywistymi znakami tabulacji , a nie spacjami, więc jeśli edytor tłumaczy naciśnięcia klawiszy tabulacji na spacje, potrzebna jest dodatkowa praca.
Jak zauważył Fred, w ten sposób stracisz końcowe „\ n”. Aby przypisać zmienną z rozwiniętymi sekwencjami odwrotnego ukośnika, wykonaj:
STR=$'Hello World\n===========\n\n'
przetestujmy to:
echo "[[$STR]]"
daje nam teraz:
[[HelloWorld===========]]
Pamiętaj, że $ „” jest inny niż $ „”. Drugi wykonuje tłumaczenie zgodnie z bieżącymi ustawieniami narodowymi. Dla deital patrz sekcja CYTOWANIE w man bash.
Odpowiedzi:
W
bash
możesz użyć składniPojedyncze cudzysłowy poprzedzone a
$
to nowa składnia, która pozwala wstawiać sekwencje specjalne w ciągach znaków.Również
printf
wbudowany pozwala zapisać wynikowy wynik w zmiennejOba rozwiązania nie wymagają podpowłoki.
Jeśli poniżej musisz wydrukować ciąg, powinieneś użyć podwójnych cudzysłowów, jak w poniższym przykładzie:
ponieważ gdy drukujesz ciąg bez cudzysłowów, znak nowej linii jest konwertowany na spacje.
źródło
str=$'Hello World\n===========\n'
? zmienne podstawienie?zsh
iksh
; jednak NIE jest zgodny z POSIX.str=$"My $PET eats:\n$PET food"
? To podejście działa w przypadku podwójnych cytatówMożesz wstawić dosłowne znaki nowej linii w pojedynczych cudzysłowach (w dowolnej powłoce w stylu Bourne / POSIX).
W przypadku ciągu wielowierszowego dokumenty tutaj są często wygodne. Ciąg jest podawany jako dane wejściowe do polecenia.
Jeśli chcesz zapisać ciąg w zmiennej, użyj
cat
polecenia w podstawieniu polecenia. Znaki nowego wiersza na końcu ciągu zostaną usunięte przez podstawienie polecenia. Jeśli chcesz zachować ostatnie znaki nowej linii, umieść korek na końcu i zdejmij go później. W powłokach zgodnych z POSIX możesz pisać,str=$(cat <<'EOF'); str=${str%a}
a następnie heredoc właściwy, ale bash wymaga, aby heredoc pojawił się przed nawiasem zamykającym.W ksh, bash i zsh możesz użyć
$'…'
cytowanego formularza, aby rozwinąć znaki odwrotnego ukośnika w cudzysłowach.źródło
str=$(cat <<'EOF')
nie działa tak, jak jest.)
Musi zostać umieszczony w następnym wierszu po końcu dokumentuEOF
... ale mimo to traci końcowy znak nowej linii z powodu polecenia Podstawienie.\n
instancjebash
podczas przechwytywania dokumentu tutaj w zmiennej, rozważIFS= read -r -d '' str <<'EOF'...
jako alternatywę dla podejścia ograniczającego (patrz moja odpowiedź).Czy używasz „echa”? Spróbuj „echo -e”.
źródło
echo
automatycznie doda jeden, chyba że podasz -n. (Jednak głównym celem pytania jest to, jak przekształcić te nowe wiersze w zmienną).bash
,echo -e
czyni pracę na OS X - to dlatego, żeecho
jest bash wbudowane (zamiast zewnętrznego wykonywalny) i że wbudowane obsługuje-e
. (Jako wbudowany, powinien działać na wszystkich platformach, na których działa bash; nawiasem mówiąc,echo -e
działaksh
izsh
również). Jednak zewnętrzneecho
narzędzie w systemie OS X -/bin/echo
- rzeczywiście nie obsługuje-e
.Jeśli wiele razy potrzebujesz nowego wiersza w skrypcie, możesz zadeklarować zmienną globalną zawierającą nowy wiersz. W ten sposób możesz używać go w ciągach cudzysłowów (zmienne rozszerzenia).
źródło
$''
wymagałaby podpowłoki?"My dog eats:${NL}dog food"
Z całej dyskusji oto dla mnie najprostszy sposób:
Polecenie echo musi używać podwójnych cudzysłowów .
źródło
Aby uzupełnić wspaniałe istniejące odpowiedzi:
Jeśli używasz
bash
i wolisz używać rzeczywistych znaków nowej linii dla czytelności ,read
to kolejna opcja przechwytywania dokumentu tutaj w zmiennej , która (podobnie jak inne rozwiązania tutaj) nie wymaga użycia podpowłoki.-r
zapewnia, żeread
nie interpretuje danych wejściowych (domyślnie traktowałby ukośniki specjalne, ale jest to rzadko potrzebne).-d ''
ustawia separator „rekordu” na pusty ciąg, powodującread
odczytanie całego wejścia naraz (zamiast tylko jednej linii).Zauważ, że pozostawiając
$IFS
(wewnętrzny separator pól) na wartości domyślnej$' \t\n'
(spację, tabulator, nową linię), wszelkie początkowe i końcowe białe znaki są przycinane od wartości przypisanej do$str
, w tym nowej linii tutaj-doc.(Zauważ, że chociaż treść tutaj-doc zaczyna się od linii po ograniczniku początkowym (
'EOF'
tutaj), nie zawiera wiodącej nowej linii).Zwykle jest to pożądane zachowanie, ale jeśli chcesz tę końcową linię, użyj
IFS= read -r -d ''
zamiast po prosturead -r -d ''
, ale zwróć uwagę, że wszystkie początkowe i końcowe białe znaki są następnie zachowywane.(Należy pamiętać, że przejście
IFS=
bezpośrednio doread
polecenia oznacza, że przypisanie działa tylko podczas tego polecenia, więc nie ma potrzeby przywracania poprzedniej wartości).Użycie dokumentu tutaj pozwala również opcjonalnie użyć wcięcia w celu uruchomienia ciągu wielowierszowego dla zapewnienia czytelności:
Umieszczenie
-
między znakiem<<
otwierającym doc tutaj i otwierającym ('EOF'
tutaj) powoduje, że wiodące znaki tabulacji są usuwane z ciała doc doc, a nawet ogranicznika zamykającego, ale należy pamiętać, że działa to tylko z rzeczywistymi znakami tabulacji , a nie spacjami, więc jeśli edytor tłumaczy naciśnięcia klawiszy tabulacji na spacje, potrzebna jest dodatkowa praca.źródło
musisz to zrobić w ten sposób:
Aktualizacja:
Jak zauważył Fred, w ten sposób stracisz końcowe „\ n”. Aby przypisać zmienną z rozwiniętymi sekwencjami odwrotnego ukośnika, wykonaj:
przetestujmy to:
daje nam teraz:
Pamiętaj, że $ „” jest inny niż $ „”. Drugi wykonuje tłumaczenie zgodnie z bieżącymi ustawieniami narodowymi. Dla deital patrz sekcja CYTOWANIE w
man bash
.źródło
wynik:
źródło
result+=$foo$'\n'
?$(printf %s "$foo")
zmniejszyłby końcowe znaki nowego wiersza,$foo
jeśli takie istnieją.