Bunu nasıl yapmanı önerdiğimi ve nedenini açıklayacağım, ama önce başka bir şey hakkında konuşmak istiyorum ...
set -- 'Arg 1: Line 1.' \
'Arg 2: Line 2.' \
'and so on for' \
'as long as you might like.'
var="$*"
Burada sunulan diğer çözümlerin çoğu, genişletme yöntemlerinizi değiştirerek bir kabuk değişkenin içeriğini bir şekilde etkileyebileceğinizi göstermektedir. Sizi temin ederim ki bu böyle değil.
string="some stuff here \
some more stuff here."
echo $string ${#string}
echo "$string" "${#string}"
ÇIKTI
some stuff here some more stuff here. 53
some stuff here some more stuff here. 53
Yukarıda gördüğünüz, önce alan bölünmüş bir genişleme, daha sonra genişlemenin kaynak değişkeni için bayt sayısı hakkında bir rapor, daha sonra teklif sınırlandırılmış bir genişleme ve aynı bayt sayısıdır. Çıktı farklılık gösterse de, kabuk değişkeninin içeriği $string
atama hariç hiçbir zaman değişmez.
Dahası, bunun neden olduğunu anlamadıysanız, çok geçmeden sürprizlerle karşılaşmak zorunda kalacaksınız. Tekrar deneyelim, ama biraz farklı koşullarda.
IFS=sf
echo $string ${#string}
echo "$string" "${#string}"
Aynı $string
- farklı ortamlar.
ÇIKTI
ome tu here ome more tu here. 53
some stuff here some more stuff here. 53
Alan bölme, içinde tanımlanan alan sınırlayıcılara göre gerçekleşir $IFS
. İki çeşit sınırlayıcı vardır - $IFS
boşluk ve $IFS
başka şeyler. Varsayılan olarak, üç olası boşluk değeri olan $IFS
değer alanı sekmesi newline atanır $IFS
. Yine de, yukarıda gördüğünüz gibi kolayca değiştirilir ve alan bölünmüş açılımları üzerinde ciddi etkileri olabilir.
$IFS
boşluk, sekansa göre tek bir alana ayrılır - ve bu, echo
boşluk içeren herhangi $IFS
bir boşluk sekansını içeren bir genişlemenin yalnızca tek bir boşluk olarak değerlendirmesini sağlar - çünkü echo
boşluklar üzerindeki argümanlarını birleştirir. Ancak, boşluk olmayan herhangi bir değer aynı şekilde seçilmez ve her bir sınırlayıcı her zaman kendi başına bir alan alır - yukarıdaki maddelerin genişlemesinde görülebileceği gibi.
Bu en kötüsü değil. Bunu diğerini düşünün $string
.
IFS=$space$tab$newline
cd emptydir
string=" * * * \
* * * "
echo $string ${#string}
echo "$string" "${#string}"
ÇIKTI
* * * * * * 30
* * * * * * 30
Tamam görünüyor değil mi? Peki, yine ortamı değiştirelim.
touch file1 file2 file3 file4 file5
echo $string ${#string}
echo "$string" "${#string}"
ÇIKTI
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
Woah.
Varsayılan olarak kabuk, dosya adı globs'unu, eğer eşleşebilirse genişletir. Bu durum sonrasında kendi ayrıştırma amacıyla parametre genişleme ve saha bölme ve böylece halka açık olmayan kısmı dize bu şekilde savunmasızdır. İsterseniz bu davranışı devre dışı bırakabilirsiniz set -f
, ancak POSIX uyumlu herhangi bir kabuk varsayılan olarak her zaman değişebilir.
Bu, girinti tercihlerinize uyacak şekilde genişletmelerden alıntılar yaptığınız zaman karşı karşıya olduğunuz şeylerdir. Ve buna rağmen, her durumda, genişleme davranışından bağımsız olarak, asıl değer $string
her zaman hala en son verdiğiniz andaki değerdir . Öyleyse ilk şeye geri dönelim.
set -- 'Arg 1: Line 1.' \
'Arg 2: Line 2.' \
'and so on for' \
'as long as you might like.'
var="$*"
echo "$var" "${#var}"
ÇIKTI
Arg 1: Line 1. Arg 2: Line 2. and so on for as long as you might like. 70
Bunun, kabuk sözdizimini girinti tercihlerinize uyarlamanın daha kolay bir yolu olduğuna inanıyorum. Yukarıda yaptığım şey, her bir dizgeye bir konumsal parametreye - her birinin $1
ya da gibi sayılarla referans alınabilmesi ${33}
- ve ardından birleştirilmiş değerlerini $var
özel kabuk parametresini kullanmaya atamak $*
.
Bu yaklaşım $IFS
, hatta bağışıklık değildir . Yine de, $IFS
bu konuda ek bir fayda ile ilişkisini düşünüyorum . Düşünmek:
IFS=\ ;space_split="$*"
IFS=/; slash_split="$*";IFS='
';new_line_split="$*"
echo "$space_split"
echo "$slash_split"
echo "$new_line_split"
ÇIKTI
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.
Gördüğünüz gibi $*
her argümanı "$@"
ilk baytta birleştirir $IFS
. Dolayısıyla $IFS
, farklı atanmış iken değerini kaydetmek, kaydedilen her değer için farklı alan sınırlayıcıları alır. Yukarıda gördüğünüz, bu arada, her değişken için gerçek değerdir. Hiç sınırlayıcı istemiyorsanız, şunları yaparsınız:
IFS=;delimitless="$*"
echo "$delimitless" "${#delimitless}"
ÇIKTI
Arg 1: Line 1.Arg 2: Line 2.and so on foras long as you might like. 67