W jakich przypadkach liczba spacji ma znaczenie w skryptach bash (lub innych powłokach)

14

Powiedziano mi, że spacje są ważne w bashinnych skryptach powłoki i nie powinienem zmieniać ich istnienia, chyba że wiem, co robię. Przez „zmianę istnienia” rozumiem albo wstawienie spacji między dwoma znakami spacji lub usunięcie spacji między dwoma znakami spacji, np. Zmiana var="$val"na var ="$val"lub odwrotnie. Chcę zapytać

Czy są jakieś przypadki, w których użycie jednej spacji lub wielu kolejnych spacji w skrypcie powłoki robi różnicę? .

(Oczywiście wstawianie / usuwanie spacji w cudzysłowach robi różnicę, np. Zmiana z echo "a b"na echo "a b"lub odwrotnie. Szukam przykładów innych niż ten trywialny przykład.)

Zetknąłem się z tym pytaniem, ale dotyczy ono dodawania i usuwania spacji między dwoma znakami spacji, dla których znam wiele przykładów, które mogłyby to zmienić.

Każda pomoc będzie mile widziana. Uwzględnij więcej odmian muszli, jeśli to możliwe.

Weijun Zhou
źródło

Odpowiedzi:

19

Poza cudzysłowami powłoka używa białych znaków (spacji, tabulatorów, nowego wiersza, powrotu karetki itp.) Jako separatora słów / tokenów. To znaczy:

  • Rzeczy, które nie są oddzielone białymi spacjami, są uważane za jedno „słowo”.
  • Rzeczy oddzielone co najmniej jednym białym znakiem są uważane za dwa (lub więcej) słów.

Rzeczywista liczba znaków odstępu między „rzeczami” nie ma znaczenia, o ile istnieje co najmniej jeden znak.

cas
źródło
Dziękuję Ci. Sam nie mogę znaleźć żadnego kontrprzykładu. Chcę się upewnić.
Weijun Zhou
2
Bash uważa również, że białe strony i formularze są pionowe.
fpmurphy
prawdziwe. pierwotnie napisałem „... nowe wiersze itp.”, a następnie zmieniłem go, aby wyraźnie dodać znaki powrotu karetki. przypadkowo upuścił „etc”.
cas
Co jeśli liczba spacji jest tak duża, że ​​program nie zmieści się w pamięci?
Worse_Username
7
@Worse_Username Biała spacja nie musi mieścić się w pamięci. Właśnie utworzyłem skrypt 48 GB na komputerze z 8 GB pamięci RAM i 20 GB wymiany. Poszło dobrze. Przebicie się przez całą białą przestrzeń zajęło 3 minuty, ale ostatecznie udało się uruchomić echopolecenie z dużą ilością białych znaków między poleceniem a argumentem.
kasperd
23

To prawdopodobnie oszustwo, ale to:

rm foo\ bar         # "delete the file named 'foo bar'"

różni się od tego:

rm foo\  bar        # "delete the files named 'foo ' and 'bar'"

nawet jeśli spacje nie są w cudzysłowach. ;-)

Co więcej, to:

rm \
    foo          # "delete the file named 'foo'"

różni się od tego:

rm \ 
    foo          # "delete the file named ' ', then run the command 'foo'"

mimo że wyglądają identycznie!

ruakh
źródło
Mimo że spacje nie są w cudzysłowach, odwrotny ukośnik jest funkcjonalnie podobny do formy cytowania i umieściłbym to w tej samej kategorii, co „trywialny przykład” pytania. (Jest to jednak interesujące.)
David Z
12

Jeśli nie będziemy rozmawiać o znak spacji ( U+0020), ale jakiegokolwiek znaku spacji ( U+0020, \n, \t, itd), a następnie jeden szczególny przypadek przychodzą mi na myśl: oto dokumentach.

Ten kod (używając spacji):

cat <<- 'EOF'
<space><space>foo
EOF

Wydrukuje:

  foo

Ale ten kod (używając kart):

cat <<- 'EOF'
<tab><tab>foo
EOF

Wydrukuje:

foo

Jest tak, ponieważ ( jak stwierdza POSIX ):

Jeśli operatorem przekierowania jest <<-, wszystkie wiodące znaki <tab> są usuwane z linii wejściowych i linii zawierającej ogranicznik końcowy.

nxnev
źródło
1
To jest interesujące. Myślałem o dokumentach tutaj, ale nie znałem <<-operatora. Dziękuję Ci bardzo.
Weijun Zhou
tutaj dokumenty są formą cytowanego tekstu, a nie kodu powłoki. dzielenie słów powłoki nie ma zastosowania.
cas
2

Ma to również wpływ podczas pisania instrukcji przypisania. Na przykład, jeśli powiem, FOO=xyzże utworzy zmienną środowiskową o nazwie FOOo wartości xyz, ale jeśli oddzielę równy spacją, pomyśli, że wywołuję program o nazwie FOOz arg =xyz. To ma znaczenie, jeśli chodzi o określoną składnię.

HSchmale
źródło
Zwykle FOO=xyztworzy wewnętrzną zmienną powłoki, ale nie zmienną środowiskową. Potrzebujesz set -alub export FOO=xyzdo tego (tj. Czyniąc go częścią środowiska podprocesów innych niż podpowłoka).
Hauke ​​Laging