Problem polega na tym, że otaczasz zmienną podwójnymi cudzysłowami („”). Usuń go, a wszystko będzie działało dobrze.
VAR="This displays with \
extra spaces."
echo ${VAR}
Wynik
This displays with extra spaces.
Problem polega na tym, że podwójne cytowanie zmiennej zachowuje wszystkie znaki białych znaków. Można tego użyć, jeśli jest to wyraźnie potrzebne.
Na przykład,
$ echo "Hello World ........ ... ...."
wydrukuje
Hello World ........ ... ....
A po usunięciu cudzysłowów jest inaczej
$ echo Hello World ........ ... ....
Hello World ........ ... ....
Tutaj Bash usuwa dodatkowe spacje w tekście, ponieważ w pierwszym przypadku cały tekst jest traktowany jako „pojedynczy” argument, a tym samym zachowuje dodatkowe spacje. Ale w drugim przypadku echo
polecenie otrzymuje tekst jako 5 argumentów.
Cytowanie zmiennej będzie również pomocne przy przekazywaniu argumentów do poleceń.
W poniższym poleceniu echo
pobiera tylko jeden argument jako"Hello World"
$ variable="Hello World"
$ echo "$variable"
Ale w przypadku poniższego scenariusza echo
dostaje dwa argumenty jako Hello
iWorld
$ variable="Hello World"
$ echo $variable
$IFS
są potężnym i uniwersalnym narzędziem - ale kod napisany w ten sposób nigdy nie może dać żadnych wiarygodnych wyników.*
?
[]
).Rozwiązania podane przez esuoxu i Mickaël Bucas są powszechnymi i bardziej przenośnymi sposobami na to.
Oto kilka
bash
rozwiązań (niektóre z nich powinny również działać w innych powłokach, takich jakzsh
). Po pierwsze za pomocą+=
operatora dołączającego (który działa w nieco inny sposób dla każdej zmiennej całkowitej, zmiennej zwykłej i tablicy).Jeśli chcesz wstawić nowe wiersze (lub inne białe znaki / znaki specjalne) w tekście,
$''
zamiast tego użyj cudzysłowu:Następnie za pomocą
printf -v
przypisać sformatowaną wartość zmiennejSztuczka polega na tym, że argumentów jest więcej niż specyfikatorów formatu, więc w przeciwieństwie do większości
printf
funkcji, bash używa łańcucha formatu, dopóki się nie skończy. Możesz wpisać\n
ciąg formatu lub użyć $ '' (lub obu), aby zająć się spacjami.Następnie za pomocą tablicy:
Możesz także użyć
+=
do zbudowania tekstu wiersz po wierszu (zwróć uwagę na()
):Tutaj jednak musisz pamiętać o „spłaszczeniu” tablicy, jeśli chcesz mieć całą zawartość tekstu za jednym razem
(tablice indeksowane liczbami całkowitymi są domyślnie sortowane, w przeciwieństwie do tablic asocjacyjnych) Daje to nieco większą elastyczność, ponieważ można manipulować liniami, a nawet kroić i kroić w razie potrzeby.
Wreszcie za pomocą
read
lubreadarray
i „tutaj-dokumentu”:Forma dokumentu tutaj
<<-
oznacza, że wszystkie wiodące twarde tabulatory są usuwane z danych wejściowych, więc musisz używać tabulatorów, aby wciąć tekst. Cudzysłowy"EOT"
uniemożliwiają ekspansję powłoki, więc dane wejściowe są używane dosłownie. Dziękiread
temu korzysta z danych rozdzielanych bajtami NUL, dzięki czemu odczytuje tekst rozdzielany znakiem nowej linii za jednym razem. Za pomocąreadarray
(znanegomapfile
również od wersji bash-4.0) wczytuje tablicę i-t
usuwa nowe linie w każdej linii.źródło
read
Opcja zehere document
jest bardzo miłe! Przydatne do osadzania skryptów Python i wykonywania ich za pomocąpython -c
. Robiłem toscript=$(cat <here document>)
wcześniej, aleread -r -d '' script <here document>
jest znacznie lepsze.Istnieje specjalna składnia heredoc, która usuwa tabulatory na początku wszystkich wierszy: „<< -” (zauważ dodaną kreskę)
http://tldp.org/LDP/abs/html/here-docs.html
Przykład 19-4. Wiadomość wieloliniowa, z pominiętymi zakładkami
Możesz użyć tego w następujący sposób:
Wynik:
Działa tylko z tabulatorami, a nie spacjami.
źródło
\t
działa świetnie, jeśli potrzebujesz kart. Po prostu użyjecho -e "$v"
zamiast,echo "$v"
aby włączyć znaki odwrotnego ukośnikaPozwól muszli zjadać niechciane pokarmy i następujące przestrzenie:
Jest więc możliwe ... ale pewne, że polubienie lub rozwiązanie tego rozwiązania jest kwestią gustu ...
źródło
Może możesz tego spróbować.
źródło
Tak sugeruję, abyś to zrobił, a ja wyjaśnię dlaczego, ale najpierw chcę porozmawiać o czymś innym ...
Wiele innych zaproponowanych tutaj rozwiązań wydaje się sugerować, że możesz w jakiś sposób wpłynąć na zawartość zmiennej powłoki, zmieniając metody jej rozszerzania. Zapewniam cię, że tak nie jest.
WYNIK
To, co widzisz powyżej, to najpierw rozwinięcie podzielone na pola, następnie raport o liczbie bajtów zmiennej źródłowej rozszerzenia, następnie rozszerzenie rozdzielane cudzysłowem i ta sama liczba bajtów. Chociaż dane wyjściowe mogą się różnić, zawartość zmiennej powłoki
$string
nigdy się nie zmienia, z wyjątkiem przypisania.Co więcej, jeśli nie rozumiesz, dlaczego tak się dzieje, na pewno spotka Cię kilka nieprzyjemnych niespodzianek wcześniej niż później. Spróbujmy jeszcze raz, ale w nieco innych warunkach.
To samo
$string
- inne środowisko.WYNIK
Podział pola następuje na podstawie ograniczników pól zdefiniowanych w
$IFS
. Istnieją dwa rodzaje ograniczników -$IFS
białe znaki i$IFS
cokolwiek innego. Domyślnie$IFS
przypisana jest nowa linia tabulatora przestrzeni wartości - trzy możliwe$IFS
wartości białych znaków. Można to łatwo zmienić, jak widać powyżej, i może mieć drastyczny wpływ na rozszerzenia podzielone na pola.$IFS
białe znaki będą się przemieszczały sekwencyjnie do pojedynczego pola - i dlategoecho
rozwinięcie zawierające dowolną sekwencję spacji, gdy$IFS
zawiera spację, będzie miało wartość tylko do pojedynczej spacji - ponieważecho
łączy argumenty spacji. Ale wartości inne niż spacja nie będą się zachowywać w ten sam sposób, a każdy występujący separator zawsze otrzymuje pole do siebie - jak widać w powyższym rozwinięciu rzeczy .To nie jest najgorsze. Rozważ to inne
$string
.WYNIK
Wygląda dobrze, prawda? Cóż, zmieńmy ponownie środowisko.
WYNIK
Łał
Domyślnie powłoka rozszerzy globs nazw plików, jeśli można je dopasować. Dzieje się tak po rozwinięciu parametru i podziale pola w kolejności parsowania, dlatego każdy niecytowany łańcuch jest narażony w ten sposób. Możesz wyłączyć to zachowanie,
set -f
jeśli chcesz, ale domyślnie każda powłoka zgodna z POSIX będzie zawsze globować.To jest rodzaj rzeczy, z którymi masz do czynienia, gdy upuszczasz cudzysłowy na rozszerzeniach, aby pasowały do twoich preferencji wcięcia. Mimo to, w każdym przypadku, niezależnie od zachowania podczas ekspansji, rzeczywista wartość dla
$string
zawsze jest taka, jaka była podczas ostatniego przypisania. Wróćmy więc do pierwszej rzeczy.WYNIK
Uważam, że jest to znacznie rozsądniejszy sposób dostosowania składni powłoki do preferencji wcięcia. To, co robię powyżej, polega na przypisaniu każdego łańcucha do parametru pozycyjnego - do którego każdy może się odwoływać za pomocą liczby, takiej jak
$1
lub${33}
- a następnie przypisaniu ich połączonych wartości do$var
użycia specjalnego parametru powłoki$*
.Takie podejście nie jest jednak odporne
$IFS
. Mimo to uważam jego związek z$IFS
dodatkową korzyścią w tym zakresie. Rozważać:WYNIK
Jak widać,
$*
konkatenuje każdy argument w"$@"
pierwszym bajcie w$IFS
. Zatem zapisanie jego wartości, gdy$IFS
jest ona przypisana w inny sposób, powoduje otrzymanie różnych separatorów pól dla każdej zapisanej wartości. Nawiasem mówiąc, to, co widzisz powyżej, to dosłowna wartość każdej zmiennej. Jeśli w ogóle nie chcesz ogranicznika, zrób:WYNIK
źródło
Możesz spróbować:
lub
a także można sprawdzić to na zewnątrz.
źródło
Użyj rozszerzenia podstawienia Bash
Jeśli używasz Bash, możesz użyć rozszerzenia podstawiania . Na przykład:
źródło
Jest to wariant ustawiania zmiennych podobnych do ścieżki:
Używanie
set
zastępowania$@
, które można zapisać i wykorzystać później w następujący sposób:LD_LIBRARY_PATH=$(sed 's/ :/:/g' <<< $LD_LIBRARY_PATH)
Linia eliminuje spacji przed dwukropkiem, a także możliwego spacji spływu. Jeśli tylko eliminujesz końcowe spacje, użyjLD_LIBRARY_PATH=${LD_LIBRARY_PATH%% }
zamiast tego.Całe to podejście jest wariantem doskonałej odpowiedzi mikeserv.
źródło
Nie bój się białych znaków. Po prostu usuń je przed wydrukowaniem tekstu wielowierszowego.
Wynik:
Nie ma potrzeby używania
<<-
heredoc i łamania 4-spacji wcięcia znakami tabulacji.źródło