Sözcük bölme nedir? Kabuk programlamasında neden önemlidir?


16

Split kelimesinin oynadığı rol hakkında kafam karışıyor zsh. C, Python veya MATLAB'da programlama yaparken bu konsepte maruz kalmadım ve bu, kelime bölmenin neden kabuk programlamaya özgü bir şey olduğu konusundaki ilgimi tetikledi.

Daha önce bu sitede ve diğer sitelerde kelime bölme hakkında okudum, ancak kavramın net bir açıklamasını bulamadım. Wikipedia, kelime bölme tanımına sahiptir, ancak Unix kabuklarına nasıl uygulanacağı konusunda referansları yoktur.

İşte karışıklığımın bir örneği zsh:

In Z Shell SSS , ben şöyle haber verilmektedir:

3.1: Neden gelmez $varnerede var="foo bar"ne bekliyorsunuz ki?

Çoğu Bourne kabuğu türevinde, var="foo bar" bir komuta geçildiğinde veya bir for foo in $vardöngüde kullanıldığında gibi çok kelimeli değişkenler kelimelere bölünür . Varsayılan olarak, zsh bu davranışa sahip değildir: değişken bozulmadan kalır. (Bu bir hata değildir! Aşağıya bakın.) SH_WORD_SPLITUyumluluk sağlama seçeneği vardır.

Ancak Z Shell Manual'da aşağıdakileri okudum:

SH_WORD_SPLIT (-y) <K> <S>

Alan bölünmesinin tırnaksız parametre genişletmelerinde yapılmasına neden olur. Bu seçeneğin kelime bölme ile ilgisi olmadığını unutmayın . (Bkz. Parametre Genişlemesi.)

Neden yazıyor SH_WORD_SPLITsahiptir ilgisi kelime bölme ile? Sözcük bölme, bununla ilgili olan şey değil mi?

Yanıtlar:


22

İlk mermilerin yalnızca tek bir veri türü vardı: dizeler. Ancak, genellikle bir programa bağımsız değişken olarak birden çok dosya adı iletilirken dize listelerini işlemek yaygındır. Bölme için bir başka yaygın kullanım durumu, bir komutun bir sonuç listesi çıkmasıdır: komutun çıktısı bir dizedir, ancak istenen veriler bir dize listesidir. Bir değişkenin içinde dosya adlarının bir listesini saklamak için aralarına boşluklar koyabilirsiniz. Sonra böyle bir kabuk betiği

files="foo bar qux"
myprogram $files

myprogramkabuk dizeyi $fileskelimelere böldüğü için üç argümanla çağrılır . O zaman, dosya adlarındaki boşluklar yasaktı ya da yaygın olarak Tamamlanmadı olarak kabul edildi.

Korn kabuk diziler tanıtıldı: Bir değişkende dizeleri listesini depolayabilir. Korn kabuğu, o zamanki kurulan Bourne kabuğuyla uyumlu kaldı, bu yüzden çıplak değişken genişlemeler kelime bölünmesine maruz kaldı ve dizileri kullanmak sözdizimsel bir ek yük gerektirdi. Snippet'i yukarıdaki şekilde yazarsınız

files=(foo bar qux)
myprogram "${files[@]}"

Zsh başından beri dizilere sahipti ve yazarı geriye dönük uyumluluk pahasına daha akıcı bir dil tasarımı seçti. Zsh (varsayılan genişletme kuralları altında) $varkelime bölme perfom yok; bir değişkenin içindeki bir kelime listesini saklamak istiyorsanız, bir dizi kullanmanız gerekir; ve gerçekten kelime bölme istiyorsanız, yazabilirsiniz $=var.

files=(foo bar qux)
myprogram $files

Bu günlerde, dosya adlarındaki boşluklar, hem birçok kullanıcının çalışmasını beklediği hem de birçok komut dosyasının, saldırganın dosya adlarını kontrol edebileceği güvenliğe duyarlı bağlamlarda yürütüldüğü için başa çıkmanız gereken bir şeydir. Dolayısıyla otomatik sözcük bölme genellikle sıkıntı yaratır; Bu nedenle, "$foo"belirli bir kullanım durumunda neden kelime bölmeye ihtiyacınız olduğunu anlamadığınız sürece , her zaman çift tırnak kullanmak, yani yazmak için genel tavsiyem . (Çıplak değişken genişlemelerin de zorlandığına dikkat edin.)


Teşekkürler Gilles, bu gerçekten yararlı! Kabaca konuşulan kelime bölmenin, formun dizelerini formun "word1 word2 word3"listelerine / dizilerine dönüştürdüğünü söylemek doğru "word1" "word2" "word3"mu? Ben de OP zsh belirli bir karışıklık kaynağı ile güncelledi.
Amelio Vazquez-Reina

1
@intrpc "Kelime bölme" doğal dil sözcüklerine değil $IFSkarakterlere bölünür . Dolayısıyla "alan bölme" daha iyi bir isimdir. Ancak "kelime bölme" kabuk literatüründe bu kavram için sıklıkla kullanılır. Zsh belgeleri kelimeler üzerinde tartışıyor.
Gilles 'SO- kötü olmayı bırak'

1
rcDeğişkenler ve diziler söz konusu olduğunda zsh'den daha iyi bir tasarım için ayrıca (Unix'e taşınan plan9 kabuğu) bölümüne bakın .
Stéphane Chazelas

3

Kelime bölme gerçekten kabuğa özgü değildir.

Metin girişini ayrıştırması gereken programların çoğu, ilk adım olarak bir tür sözcük bölme kullanır. Bu "kelimelerden", sayılardan, operatörlerden, dizelerden, jetonlardan ve işlemek için ihtiyaç duydukları benzer varlıklardan tanımlanmadan önce yapılır.

Kabuklara özgü olan, gömülü boşluklar, boş argümanlar, özel sınırlayıcılar vb. Birçok mermi, orada esneklik sağlamak için IFS değişkenini kullanır.


3

Bu özel Zsh durumunda, kelime ayırma, alan ayırmadan biraz farklı olarak tanımlanır.

prog a b cNasıl ayarlasanız da üç argümanı geçeceğini düşünün IFS. Bu kelime bölme.

Bunu yaparsanız , boşluk veya başka bir argüman içeriyorsa A="a b c"; prog $Aüç argümandan geçer IFS. Bu alan bölme.

Buradaki tanımlar inceliklidir. Zsh belgesinin söylemeye çalıştığı şey, bu seçeneği devre dışı bıraksanız bile prog a b c, yine de ayrı argümanlar (insanların her zaman beklediği şey) alacağıdır.


1
Uzun zamandır zsh geliştiricisi olan Bart Schaefer, gerçekten de metnin amaçlanan anlamı olduğunu doğruladı .
Stéphane Chazelas
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.