yüksek oy kullanan tek satırda iç içe çift tırnak


20

> 3.5K oy içeren bir StackOverflow yanıtıDIR , geçerli bash betiğinin dizinine atamak için bu tek astarı içerir:

DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"

Yuvalanmış çift tırnak işaretinden şaşkınım. Anlayabildiğim kadarıyla, aşağıdaki parçalar çift tırnaklı:

"$( cd "
"${BASH_SOURCE[0]}"
" && pwd )"

... ve =(yani $( dirnameve )) 'nin sağındaki diğer her şey alıntılanmamıştır. Başka bir deyişle, 2., 4. ve 6. "karakterlerin "sırasıyla 1., 3. ve 5. karakterleri "kapattığını" varsayıyorum .

Çift tırnakların ne elde ettiğini anlıyorum "${BASH_SOURCE[0]}", ancak diğer iki çift tırnak arasındaki amaç nedir?

Öte yandan, (ve yüksek oy puanı buna rağmen), yukarıdaki pasaj yanlışsa, nominal amacına ulaşmanın doğru yolu nedir?

( Nominal niyetle demek istediğim: tarafından döndürülen dizine pwdilk cd-ing'ten sonra döndürülen değeri toplayın ve üst kabuğu değiştirmeden kalacak dirname "${BASH_SOURCE[0]}"şekilde cd-ing'i bir alt kabukta yapın $PWD).


1
çünkü $ bir özelliğin var (...): $( here, it's a subshell, but you are writing code as if you were writing it on the "first level" of the shell .... ).
Olivier Dulac

Docker kurulum betiği nedeniyle buraya geldim. lsb_dist="$(. /etc/os-release && echo "$ID")"; echo "$lsb_dist"
Dağıtımın

Satırdaki boşluklara gerek olmadığına dikkat edin: DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"çalışır.
David Tonhofer

Yanıtlar:


12

bashYapbozunuz girişi (ve genel olarak kabuğun) girişi nasıl ayrıştırdığı konusunda doğru değil . İçinde:

DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"

Birincisi, bashatamanın sağ tarafını uzun bir dizeye ayrıştırın $( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )çünkü çift ​​tırnak çift tırnak içinde görünebilir .

Bundan sonra, bashkomut değişikliğini ayrıştırmaya başlayın. Komut yerine parantez içinde açık parantezin ardından gelen tüm karakterler, komut değiştirme içinde komutu oluşturmak için kullanıldığından, şunları elde edersiniz:

cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd

Kabuk bu bileşik komutu ayrıştırmaya devam eder, iki parçaya ayırır:

  • cd "$( dirname "${BASH_SOURCE[0]}" )"
  • pwd

Daha sonra aynı ayrıştırma kuralını uygulamak cd "$( dirname "${BASH_SOURCE[0]}" )", ancak bu kez, çift tırnak gereksiz değildir, ancak mantıklıdır. Sonuçta alan bölünmesini önlerler $( dirname "${BASH_SOURCE[0]}" )ve ayrıca genişlerler ${BASH_SOURCE[0]}(en dıştaki çift tırnakların aksine , değişken atamanın RHS'sinde gereklisplit+glob olmayacaktır ).


Bu kural , tüm POSIX kabuğunda komut değiştirme için geçerlidir . POSIX spesifikasyonunun Jeton Tanıma bölümünde daha ayrıntılı bir bulmaca okuyabilirsiniz .


21

Biri içeri girdikten sonra $(...)alıntılar baştan başlar.

Başka bir deyişle, "..."ve $(...)kutu yuva birbiri içinde. İşlem ikamesi, $(...)bir veya daha fazla tam çift ​​tırnaklı dizgi içerebilir . Ayrıca, çift tırnaklı dizeler bir veya daha fazla tam proses ikamesi içerebilir . Ancak, birbirine geçmezler. Bu nedenle, bir işlem ikamesi içinde başlayan çift tırnaklı bir dize asla onun dışında veya tam tersi şekilde uzanmaz.

Bu yüzden şunu düşünün:

DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"

İç $(...)kısım:

dirname "${BASH_SOURCE[0]}"

Yukarıda ${BASH_SOURCE[0]}çift ​​alıntıdır. Bunun dışında çift veya tek tırnak, çift tırnaklı $(...)olduğunu belirlerken önemsizdir ${BASH_SOURCE[0]}.

Dış $(...)kısım şunları içerir:

cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd

Burada ifade $( dirname "${BASH_SOURCE[0]}" )çift ​​tırnak içine alınmıştır. Dışında alıntılar olması $(...), içinde ne olduğunu düşünürken önemsizdir. İç kısımda alıntılar $(...)olması da önemsizdir.

Çift tırnak işaretleri şu şekilde eşleşir:

resim açıklamasını buraya girin


Ne demek istiyorsun irrelevant? Dış parantezin dışında, diğer tümlerin kendi anlamı vardır.
cuonglm

4
Ve bu yüzden backticks kullanmamalısınız: Alıntı kuralları son derece garip ve sezgisel değil.
Wildcard

“Bundan $(...)daha sıkı bağlanır ” cümlesi bir "..."anlam ifade etmiyor. Bunlar operatörleri ifade etmezler ve aralarında hiyerarşi yoktur (eğer varsa, tırnakların parantez içinde veya parantezlerin tırnak içinde olamayacağı anlamına gelir, ancak durum böyle değildir). Teknik terim bu $(…)ve "…"yuva.
Gilles 'SO- kötü olmayı bırak

@Gilles Çok iyi. Sadece konsepti daha iyi ele geçirme umuduyla yeniden ifade ettim.
John1024
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.