İçindekiler
Shell betiklerinde <<EOF ile oluşturulan here-document yapısı, çok satırlı metinleri bir komuta aktarmanın en rahat yollarından biridir. Ancak kodu daha okunaklı yapmak için sınırlayıcıya girinti eklediğinizde Shell aniden metnin hiç bitmediğini düşünebilir. Sorun görsel hizalama değil, kapanış sınırlayıcısının karakter karakter eşleşmek zorunda olmasıdır.
``
Here-document nasıl çalışır?
Here-document, bir komutun standart girdisine çok satırlı içerik gönderir. Genel sözdizimi şöyledir:
cat <<EOF
Merhaba dünya
EOF
Shell, <<EOF ifadesini gördüğünde sonraki satırları okumaya başlar. Yalnızca tamamı EOF olan bir satırla karşılaştığında okumayı bırakır. Buradaki EOF özel bir anahtar kelime değildir; SON, METIN veya başka bir ad da seçilebilir.
Bunu bir eşitlik gibi düşünebiliriz. Açılışta tanımlanan sınırlayıcı $D$ olsun. Kapanışın geçerli olması için okunan satır $L$ şu koşulu sağlamalıdır:
\[L = D\]Satırın başında boşluk varsa gerçekte $L = \text{“ EOF”}$ olur. Bu değer EOF ile aynı değildir. Dolayısıyla $L \neq D$ ve here-document kapanmaz.
Girinti neden sınırlayıcıyı bozar?
Aşağıdaki kod estetik görünse de hatalıdır:
if true; then
cat <<EOF
Kullanıcı bulundu.
EOF
fi
Kapanış satırındaki dört boşluk da verinin parçasıdır. Shell EOF ararken ` EOF` görür. Bash çoğunlukla dosyanın sonuna kadar okumayı sürdürür ve sınırlayıcının bulunamadığını belirten bir uyarı verir.
| Yazım | Sonuç | Neden |
|---|---|---|
EOF |
Çalışır | Birebir eşleşir |
| ` EOF` | Çalışmaz | Başında boşluk vardır |
EOF |
Çalışmaz | Sonunda boşluk vardır |
\tEOF ve <<-EOF |
Çalışır | Baştaki sekmeler temizlenir |
Çözüm 1: Sınırlayıcıyı satır başına taşımak
En taşınabilir çözüm, kapanış sınırlayıcısını girintisiz yazmaktır:
if true; then
cat <<EOF
Kullanıcı bulundu.
İşlem başlatılıyor.
EOF
fi
Bu yaklaşım POSIX uyumludur. Dezavantajı, metnin çevresindeki kodla hizalanmamasıdır. Buna rağmen farklı Shell ortamlarında güvenilir davranması nedeniyle genellikle en güvenli seçimdir.
Çözüm 2: <<-EOF ve sekme kullanmak
Tireli biçim, here-document satırlarının başındaki sekme karakterlerini kaldırır:
if true; then
cat <<-EOF
Kullanıcı bulundu.
İşlem başlatılıyor.
EOF
fi
Bu kodda girintiler gerçek tab karakteri olmalıdır. Dört boşluk, ekranda sekmeyle aynı görünebilir fakat aynı karakter değildir. Matematiksel olarak temizleme işlemini $T$ ile gösterirsek, <<- için karşılaştırma $T(L)=D$ biçiminde yapılır; burada $T$, yalnızca baştaki tab karakterlerini siler.
| Özellik | <<EOF |
<<-EOF |
|---|---|---|
| Baştaki boşlukları siler | Hayır | Hayır |
| Baştaki sekmeleri siler | Hayır | Evet |
| Girintili kapanışa izin verir | Hayır | Yalnızca tab ile |
| POSIX desteği | Evet | Evet |
Değişken genişletmesini de unutmayın
Sınırlayıcının tırnaklanması, içerikte değişkenlerin çalışıp çalışmayacağını belirler:
name="Ada"
cat <<EOF
Merhaba $name
EOF
cat <<'EOF'
Bu kez $name aynen yazılır.
EOF
İlk blok Merhaba Ada üretirken ikinci blok $name metnini değiştirmeden basar. Girinti problemiyle tırnaklama birbirinden ayrı konulardır: <<- sekmeleri yönetir, 'EOF' ise değişken ve komut genişletmesini engeller.
Pratik hata ayıklama
Editörünüz boşluk ve tab karakterlerini görünür yapabiliyorsa bu özelliği açın. Ayrıca sorunlu satırı incelemek için sed -n l dosya.sh kullanılabilir; tab karakterleri genellikle \t olarak görünür. Özetle kapanış sınırlayıcısını tamamen sola yaslamak en sade çözümdür. Kod hizalaması şartsa <<-EOF kullanın, fakat girintinin boşluk değil gerçek sekme olduğundan emin olun. Shell gözünde güzel hizalama değil, baytların birebir eşleşmesi önemlidir.
Yorumlar