bash: özel karakterler içeren komut satırı argümanlarının iletilmesi


31

Kendime programnormal bir ifadeye giriş gerektiren bir Linux programı yazdım .

Programı bashkabukta çağırmak ve bu normal ifadeyi programa komut satırı argümanı olarak iletmek istiyorum (başka komut satırı argümanları da var). Tipik bir düzenli ifade gibi görünüyor

[abc]\_[x|y]

Maalesef karakterler [, ]ve |özel karakterlerdir bash. Böylece, arayarak

program [abc]\_[x|y] anotheragument

çalışmıyor Bir tür kaçış karakterleri veya tırnak işaretleri vb. Kullanarak ifadeyi geçmenin bir yolu var mı?

(Çağrılar program "[abc]\_[x|y] anotheragument"da çalışmıyor çünkü iki argümanı bir olarak yorumluyor.)

Yanıtlar:


27

Ya yapabilirsiniz

  1. Her özel sembolden ters eğik çizgiyle (içinde olduğu gibi \[abc\]_\[x\|y\]) kaçın veya
  2. Argümanın tamamını çift tırnak (içinde olduğu gibi "[abc]_[x|y]").

DÜZENLEME: As bazı dikkat çekmişlerdir, dobleqouting değişken genişleme ne de komut ikamesi önlemez. Bu nedenle, regex'iniz bash tarafından bunlardan biri olarak yorumlanabilecek bir şey içeriyorsa, bunun yerine tek tırnak kullanın.


4
Bash olarak, gelmez çift alıntı değil değişkenleri genişleyen baypas "$HOME"veya parametreleri "${USER:-root}"ya formda, komut "$(date)"veya "`date`", aritmetik "$((1 + 2))", tarih genişlemesi "!!"veya ters eğik çizgi kaçan "\\". Bunun yerine tek tırnak kullanın. Bash kılavuzunun man sayfasına bakınız, "Quoting" başlığı.
Flimm

25

Tek tırnak kullanın. Tek tırnak, hiçbir karakterin yorumlanmamasını sağlar.

$ printf %s 'spaces  are  not  interpreted away
neither are new lines
nor variable names $TESTING
nor square brackets [TESTING]
nor pipe characters or redirection symbols | > <
nor the semicolon ;
nor backslashes \a \b \c \\
the only thing that does not work is the single quote itself
'

Tek bir fiyat teklifi eklemeniz gerekirse iki çözüm vardır:

$ printf '%s\n' '[ Don'"'"'t worry, be happy! ]'
[ Don't worry, be happy! ]
$ printf '%s\n' '[ Don'\''t worry, be happy! ]'
[ Don't worry, be happy! ]

Haklısın +1
Deccal

6

Başına man bash

Üç alıntı mekanizması vardır: kaçış karakteri , tek tırnak işareti ve çift tırnak işareti.

Alınmamış ters eğik çizgi ( \ ), kaçış karakteridir . <newline> dışında bir sonraki karakterin değişmez değerini korur. Bir \ <newline> çifti görünürse ve ters eğik çizgi kendiliğinden alıntılanmazsa, \ <newline> bir satır devamı olarak değerlendirilir (yani, giriş akışından kaldırılır ve etkin bir şekilde yoksayılır).

Karakterleri tek tırnak işaretleri içine alma, tırnak içindeki her karakterin gerçek değerini korur. Önceden ters eğik çizgiden önce olsa bile, tek tırnaklar arasında tek bir teklif oluşmayabilir.

Karakterleri çift tırnak işareti içine almak, $ , ` , \ ve tırnak işareti genişletme işlevi etkinken, tırnak işaretleri içindeki tüm karakterlerin değişmez değerini korur ! . $ Ve ` karakterleri özel anlamlarını çift tırnak içinde tutar. Ters eğik çizgi yalnızca özel karakterini yalnızca aşağıdaki karakterlerden biri tarafından takip edildiğinde korur: $ , ` , " , \ veya <newline> İkili tırnak içinde ters eğik çizgi ile çift tırnak işaretine alınabilir. olmadıkça gerçekleştirilecektir! çift ​​tırnak şeklinde görünen bir ters eğik çizgi kullanılarak kaçtı. Önündeki ters eğik çizgi ! kaldırılmaz.

Özel parametreler * ve @ , çift tırnak içine alındığında özel bir anlama sahiptir (aşağıdaki PARAMETRELER'e bakın).

$ ' String ' formundaki kelimeler özel olarak değerlendirilir. Sözcük , ANSI C standardında belirtildiği şekilde ters eğik çizgi karakterleriyle değiştirilen dizeye genişler . Ters eğik çizgi kaçış dizileri, varsa, aşağıdaki gibi çözülür:

       \ bir      uyarı (zil)
        \ b      geri al
        \ e 
       \ e      bir kaçış karakteri
        f \      form besleme
        \ n      yeni satır
        \ R      satır başı
        \ t      yatay sekme
        \ V      düşey sekme
        \\      eğik çizgi
        \'      tek tırnak
        \"      çift tırnak
        \ nnn    Sekizlik karakter, nnn sekizlik değeri
              (bir ila üç hane)
       \ x HH    , değeri sekiz bitlik bir karakter onaltılık değeridir HH
              (bir veya iki altıgen rakam)
       \ u hhhh değerdir Unicode (ISO / IEC 10646) karakteri
              onaltılık değer HHHH (bir ila dört onaltılık basamak)
        \ U HHHHHHHH
              değeri Unicode (ISO / IEC 10646) karakteri
              onaltılık değer HHHHHHHH (bir ila sekiz onaltılık basamak)
        \ c x     a control- x karakteri

Genişletilmiş sonuç, sanki dolar işareti yokmuşçasına, tek alıntı olarak verilir.

Dolar işaretinden ( $ " string " ) önce gelen çift tırnaklı bir dize , dizgenin geçerli yerel ayara göre çevrilmesine neden olur. Geçerli yerel ayar C veya POSIX ise, dolar işareti yoksayılır. Dize çevrilir ve değiştirilirse, değiştirme iki kez alıntılanır.


2

\Onlardan kaçmak için özel karakterlerin önünde ters eğik çizgi ( ) kullanabilirsiniz :

john @ awesome: ~ # echo \ &
&

2

Bir regex olarak yararlı olmasa da, bazı karakter dizileri Bash değişken adları olarak yorumlanabilir. Bunun olmasını önlemek ve genişlemelerini önlemek için, çift tırnak yerine tek tırnak kullanın:

program '[abc]_[x|y]' anotherargument

Her argümanı ayrı olarak (alıntı yapmaları gerekiyorsa) alıntı yapın, böylece bağımsız argümanlar olarak yorumlanırlar. Ayrıca bazı durumlarda dizileri de kullanabilirsiniz:

param_array=('[abc]_[x|y]' anotherargument)    # create an array
param_array+=(yetanother)     # append another element to the array
program "${param_array[@]}"   # use the array elements as arguments to program

1
program "[abc]_[x|y]"
program "[abc]_[x|y]" anotherargument

0

Onlardan kaçmak iyi çalışmalı:

  programm \[abc\]_\[x\|y\]

0

Desen nereden geliyor? Sabit mi yoksa bir kullanıcıdan mı? Komut dosyasını yerel sistemde çağıran kullanıcı mı yoksa uzaktaki biri mi?

Kabuğu yorumlamasını engellemek için verileri kaydırmak için tırnak kullanın. İki seçenek var:

  1. Hala bazı yorumlara izin veren çift tırnak ($ ​​genişletin ve `geri dönüşler ')
  2. Her şeyi gerçek anlamıyla geçen tek tırnak

Çünkü $regexps'de geçerli bir karakter (satır sonu / arabellek), değişkende saklamadığınız sürece regexp'yi tutmak için tekli tırnak kullanmak istersiniz. Güvenilmeyen birinden rastgele veri alıyorsanız, tek tırnak işareti 'ile değiştirmeniz '"'"'ve sonra sarmanız gerekir .

O Not [abc]_[x|y]sizin gibi görünüyor istiyorum eşleşecek xya yaslında üç karakterlerden birini eşleşen de, diğer xy|. Köşeli parantez içindeki ve yalnızca -aralıklardaki ve ^a'nın olumsuzluk başlangıcındaki karakterleri eşleştirir . Öyleyse, [abc]_(x|y)neyi kastettiğiniz olabilir ve parantezler kabuk için özel olan karakterlerdir. Köşeli parantezler kabuğa özel değildir , sadece oldukları gibi görünür. Çift köşeli parantez [[ ... ]]özeldir.


Bu (ı değiştirilmesi için özellikle talimat takdir Burada en doğru cevapları biridir 'ile '"'"', ancak, yine de doğru değildir). [Kabuk için özel bir karakter IS, yol genişletme yaparken joker karakterlerde kullanılır (hangi kabuk işaretlenmemiş her şey için yapar).
jpalecek

Değişken abonelik veya küreselleşme gibi bazı bağlamlarda özeldir, ancak yine de yazabilir foo=a[b]ve sonra echo $foodizenin alıntı yapılması gerekmediğini görebilirsiniz. Haklısın, çok kısaydım.
Phil P,

Eğer şanssız iseniz, orada bir dosya abgeçerli dizinde ve sonra fooiçerecektir abziyade a[b]. Köşeli parantezinizden alıntı yapın, millet.
clacke

(Netlik için: Alıntı yapıyorum (orjinal cevap açıklandığı gibi, alıntı yapmak için zorladığım yer) ve bu, ele aldığım bir raydan çıkmadır). Bu iddia beni şaşırttı, ben de test ettim. Zsh veya bash için doğru değil, BSD / bin / sh için de geçerlidir. Bu POSIX’e aykırı ve standart olmayan bir davranış. Zsh'de setopt glob_assignbu davranışı da etkinleştirebilirsiniz, bu nedenle alıntı yapmak en güvenli cevaptır.
Phil P
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.