Birden fazla teklif seviyesiyle (gerçekten, birden fazla ayrıştırma / yorumlama düzeyi) ilgilenmek karmaşıklaşabilir. Bazı şeyleri akılda tutmaya yardımcı olur:
- Her “alıntı seviyesi” potansiyel olarak farklı bir dil içerebilir.
- Alıntı yapma kuralları dile göre değişir.
- Birden fazla veya iki iç içe seviyeyle uğraşırken, genellikle "aşağıdan yukarıya" (en içten dışa doğru) çalışmak en kolaydır.
Teklif Seviyesi
Örnek komutlarınıza bakalım.
pgrep -fl java | grep -i datanode | awk '{print $1}'
Kabuğun içinde regex: (yukarıda) İlk örnek komut Dört dil kullanır pgrep , içinde regex grep (regex dilinden farklı olabilir pgrep ) ve awk . Dahil olan iki yorum düzeyi vardır: kabuk ve ilgili komutların her biri için kabuktan sonra bir seviye. Yalnızca bir açık tırnak düzeyi vardır ( awk içine kabuk alıntı ).
ssh host …
Sonra üstüne ssh seviyesi eklendi . Bu etkili bir başka kabuk seviyesidir: ssh komutun kendisini yorumlamaz, uzak uçtaki bir kabuğa (örneğin (örneğin) sh -c …
) verir ve bu kabuk dizeyi yorumlar.
ssh host "sudo su user -c …"
Daha sonra su kullanarak ortasına başka bir kabuk seviyesi eklemeyi istediniz ( komut bağımsız değişkenlerini yorumlamayan sudo aracılığıyla , böylece onu görmezden gelebiliriz). Bu noktada, üç iç içe geçme seviyesine sahipsiniz ( awk → kabuk, kabuk → kabuk ( ssh ), kabuk → kabuk ( su kullanıcısı -c ), bu yüzden "aşağı, yukarı" yaklaşımını kullanmanızı öneriyorum. mermileriniz Bourne uyumludur (ör. sh , kül , kısa çizgi , ksh , bash , zsh , vb.) Başka tür bir kabuk ( balık , rc, vb.) farklı sözdizimi gerektirebilir, ancak yöntem hala geçerlidir.
Altüst
- En iç düzeyde temsil etmek istediğiniz dizgiyi formüle edin.
- Bir sonraki en yüksek dilin alıntı repertuarından bir alıntı mekanizması seçin.
- İstediğiniz dizgiyi seçtiğiniz alıntı mekanizmasına göre alıntı yapın.
- Hangi alıntı mekanizmasının nasıl uygulanacağı konusunda birçok değişiklik vardır. El ile yapmak genellikle bir uygulama ve tecrübe meselesidir. Programlı olarak yaparken, en doğru olanı seçmek en iyisidir (genellikle “en gerçek” (en az kaçış)).
- İsteğe bağlı olarak, elde edilen alıntı dizesini ek kodla kullanın.
- İstediğiniz alıntı / yorumlama seviyesine henüz ulaşmadıysanız, sonuçlanan alıntı dizgiyi (artı herhangi bir kod) alın ve 2. adımda başlangıç dizgisi olarak kullanın.
Anlambilimsel Değişken Alıntılama
Burada akılda tutulması gereken şey, her dilin (alıntılama seviyesinin) aynı alıntılama karakterine biraz farklı anlambilim (veya çok daha farklı anlambilim) verebilmesidir.
Çoğu dilde “edebi” bir alıntı mekanizması vardır, ancak tam anlamıyla ne kadar hazır olduklarına göre değişir. Bourne benzeri mermilerin tekli alıntısı gerçektir (yani tek bir alıntı karakterinin kendisini alıntılamak için kullanamazsınız). Diğer diller (Perl, Ruby) daha az onlar yorumlamak o değişmez olduğu bazı sivil anlamıyla tek tırnaklı bölgelerin içinde ters eğik çizgi dizileri (özellikle, \\
ve \'
sonuç \
ve '
ancak diğer ters eğik çizgi dizileri aslında edebi vardır).
Alıntılama kurallarını ve genel sözdizimini anlamak için dillerinizin her birinin belgelerini okumak zorunda kalacaksınız.
Senin örnek
Örneğinizin en içsel seviyesi bir awk programıdır.
{print $1}
Bunu bir kabuk komut satırına yerleştireceksiniz:
pgrep -fl java | grep -i datanode | awk …
Biz (en azından) alan ve korumak için gereken $
de awk programı. Belirgin seçim, tüm programın etrafında tek bir alıntı kullanmaktır.
Yine de başka seçenekler var:
{print\ \$1}
doğrudan boşluktan kaçmak ve $
{print' $'1}
tek alıntı sadece boşluk ve $
"{print \$1}"
bütünü iki katına çıkarmak ve kaçmak $
{print" $"1}
sadece boşluğu iki katına çıkarır ve $
bu kuralları biraz bükebilir ( $
çift tırnaklı bir dizgenin sonunda çıkılmaz), ancak çoğu kabukta işe yaradığı görülmektedir.
Program açık ve kapalı küme parantezleri arasında virgül kullanıyorsa, bazı mermilerdeki "küme genişlemesini" önlemek için virgül veya küme parantezlerinden alıntı yapmamız veya kaçmamız gerekir.
Biz almak '{print $1}'
ve kabuk “kod” geri kalanında gömün:
pgrep -fl java | grep -i datanode | awk '{print $1}'
Sonra, bunu su ve sudo ile çalıştırmak istediniz .
sudo su user -c …
su user -c …
aynen some-shell -c …
(başka bir UID altında çalışanlar hariç) olduğu gibi , su da başka bir kabuk seviyesi ekler. sudo , argümanlarını yorumlamaz, bu yüzden herhangi bir alıntı seviyesi eklemez.
Komut dizemiz için başka bir kabuk seviyesine ihtiyacımız var. Tek alıntıyı tekrar seçebiliriz, ancak mevcut tek alıntılara özel işlem yapmak zorundayız. Her zamanki gibi şöyle görünüyor:
'pgrep -fl java | grep -i datanode | awk '\''{print $1}'\'
Burada kabuğun yorumlayacağı ve birleştireceği dört dize vardır: ilk tek alıntı dize ( pgrep … awk
), kaçan bir tek alıntı, tek alıntı awk programı, başka bir kaçan tek alıntı.
Elbette birçok alternatif var:
pgrep\ -fl\ java\ \|\ grep\ -i\ datanode\ \|\ awk\ \'{print\ \$1}
önemli olan her şeyden kaçmak
pgrep\ -fl\ java\|grep\ -i\ datanode\|awk\ \'{print\$1}
Aynı, ancak gereksiz boşluk olmadan ( awk programında bile !)
"pgrep -fl java | grep -i datanode | awk '{print \$1}'"
her şeyi çift alıntı, kaçış $
'pgrep -fl java | grep -i datanode | awk '"'"'{print \$1}'"'"
varyasyonunuz; kaçmak yerine (bir karakter) çift tırnak (iki karakter) kullanmaktan normal yoldan biraz daha uzun
İlk seviyede farklı fiyat teklifi kullanmak, bu seviyedeki diğer değişikliklere izin verir:
'pgrep -fl java | grep -i datanode | awk "{print \$1}"'
'pgrep -fl java | grep -i datanode | awk {print\ \$1}'
İlk değişkeni sudo / * su * komut satırına gömmek şunu verir:
sudo su user -c 'pgrep -fl java | grep -i datanode | awk '\''{print $1}'\'
Aynı dizeyi diğer herhangi bir tek kabuk seviyesi bağlamında (örn. ssh host …
) Kullanabilirsiniz .
Sonra, üstüne bir ssh seviyesi eklediniz . Bu etkili bir başka kabuk seviyesidir: ssh komutun kendisini yorumlamaz, ancak uzak uçtaki bir kabuğa (örneğin (örneğin) sh -c …
) verir ve bu kabuk dizeyi yorumlar.
ssh host …
İşlem aynıdır: dizeyi alın, bir alıntı yöntemi seçin, kullanın, gömün.
Tekrar tek tırnak işareti kullanmak:
'sudo su user -c '\''pgrep -fl java | grep -i datanode | awk '\'\\\'\''{print $1}'\'\\\'
Şimdi, yorumlanmış ve birleştirilen on bir dize var:, 'sudo su user -c '
kaçılmış tek fiyat teklifi, 'pgrep … awk '
kaçılmış tek alıntı, kaçış ters eğik çizgi, iki kaçış tek tırnak işareti, tek alıntı kâğıt programı, kaçılmış tek bir teklif, kaçış ters eğik çizgi ve son kaçış tek bir teklif .
Son form şöyle görünür:
ssh host 'sudo su user -c '\''pgrep -fl java | grep -i datanode | awk '\'\\\'\''{print $1}'\'\\\'
Bu, elle yazmak için biraz hantaldır, ancak kabuğun tek tırnak işaretinin gerçek niteliği, hafif bir değişimi otomatikleştirmeyi kolaylaştırır:
#!/bin/sh
sq() { # single quote for Bourne shell evaluation
# Change ' to '\'' and wrap in single quotes.
# If original starts/ends with a single quote, creates useless
# (but harmless) '' at beginning/end of result.
printf '%s\n' "$*" | sed -e "s/'/'\\\\''/g" -e 1s/^/\'/ -e \$s/\$/\'/
}
# Some shells (ksh, bash, zsh) can do something similar with %q, but
# the result may not be compatible with other shells (ksh uses $'...',
# but dash does not recognize it).
#
# sq() { printf %q "$*"; }
ap='{print $1}'
s1="pgrep -fl java | grep -i datanode | awk $(sq "$ap")"
s2="sudo su user -c $(sq "$s1")"
ssh host "$(sq "$s2")"