Tak sugeruję, abyś to zrobił, a ja wyjaśnię dlaczego, ale najpierw chcę porozmawiać o czymś innym ...
set -- 'Arg 1: Line 1.' \
'Arg 2: Line 2.' \
'and so on for' \
'as long as you might like.'
var="$*"
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.
string="some stuff here \
some more stuff here."
echo $string ${#string}
echo "$string" "${#string}"
WYNIK
some stuff here some more stuff here. 53
some stuff here some more stuff here. 53
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.
IFS=sf
echo $string ${#string}
echo "$string" "${#string}"
To samo $string
- inne środowisko.
WYNIK
ome tu here ome more tu here. 53
some stuff here some more stuff here. 53
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 dlatego echo
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
.
IFS=$space$tab$newline
cd emptydir
string=" * * * \
* * * "
echo $string ${#string}
echo "$string" "${#string}"
WYNIK
* * * * * * 30
* * * * * * 30
Wygląda dobrze, prawda? Cóż, zmieńmy ponownie środowisko.
touch file1 file2 file3 file4 file5
echo $string ${#string}
echo "$string" "${#string}"
WYNIK
file1 file2 file3 file4 file5 file1 file2 file3 file4 file5 file1 file2 file3 file4 file5 file1 file2 file3 file4 file5 file1 file2 file3 file4 file5 file1 file2 file3 file4 file5 30
* * * * * * 30
Ł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.
set -- 'Arg 1: Line 1.' \
'Arg 2: Line 2.' \
'and so on for' \
'as long as you might like.'
var="$*"
echo "$var" "${#var}"
WYNIK
Arg 1: Line 1. Arg 2: Line 2. and so on for as long as you might like. 70
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ć:
IFS=\ ;space_split="$*"
IFS=/; slash_split="$*";IFS='
';new_line_split="$*"
echo "$space_split"
echo "$slash_split"
echo "$new_line_split"
WYNIK
Arg 1: Line 1. Arg 2: Line 2. and so on for as long as you might like.
Arg 1: Line 1./Arg 2: Line 2./and so on for/as long as you might like.
Arg 1: Line 1.
Arg 2: Line 2.
and so on for
as long as you might like.
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:
IFS=;delimitless="$*"
echo "$delimitless" "${#delimitless}"
WYNIK
Arg 1: Line 1.Arg 2: Line 2.and so on foras long as you might like. 67