Bash içinde ünlem işareti (!) Kullanılamaz mı?


86

Curl komutunu !, yolunda bir ünlem işareti ( ) bulunan bir http URL'sine erişmek için kullanmaya çalışıyorum . Örneğin:

curl -v "http://example.org/!287s87asdjh2/somepath/someresource"

Konsol ile cevap verir bash: ... event not found.

Burada neler oluyor? ve ünlem işaretinden kaçmak için uygun sözdizimi ne olurdu?


Bash 4.4 + 'da çözüldü
Isaac

Yanıtlar:


98

Ünlem işareti bash'ta tarihin genişlemesinin bir parçası. Bunu kullanmak için karakterden önce tek tırnak içine alın (örneğin:) 'http://example.org/!132'veya doğrudan ters eğik çizgi ( \) ile çıkmanız gerekir (örn :) "http://example.org/\!132".

Çift tırnak içinde, ünlemden önceki bir ters eğik çizginin tarihin genişlemesini önlediğini unutmayın, ancak böyle bir durumda ters eğik çizginin kaldırılmadığını unutmayın. Bu yüzden tek tırnak kullanmak daha iyidir, bu yüzden curlURL'nin bir parçası olarak değişmez bir ters eğik çizgi geçmiyorsunuz .


8
"http://example.org/\!132"aslında ters eğik çizgiyi yorumlamadan genişler (POSIX uyumluluk nedenleri sanırım).
Chris Down

@ChrisDown, metindeki ikinci seçeneğimin bu olduğunu açıklamaya çalıştım. Karışıklık potansiyelini gösterdiğiniz için teşekkür ederiz.
Daniel Pittman

6
Kayıt için: "!" Kaçmayı denemek için taşınabilir değil. En iyi uygulamalar önerisi her zaman alıntı yapmaktır (tekli tırnaklar) "!". İlgili: "^" (şapka), taşınabilirlik için fiyat teklifi gerektiren bir meta karakter değil. En sonunda, "!" if ifadesinde kullanılmamalıdır; mümkünse test etmek için bir argüman olarak kullanın (yine Solaris / bin / sh nedeniyle).
Nicholas Wilson

5
Sadece tek tırnak benim için çalıştı. Zsh hala yorumlu \!ve çift tırnaklıydı.
orkoden,

1
Solaris'te (eski XPG4 öncesi kabuk hurdası), '^' bir takma addır |ve bir boru oluşturmak için kullanılır. Müşterilere komut dosyaları gönderiyorsanız ve hangi kabuğu çalıştırdıklarından emin değilseniz, hepsini test etmeniz gerekir!
Nicholas Wilson

61

Daniel tarafından verilen cevabın yanı sıra, kullanmazsanız tarihin genişlemesini tamamen kapatabilirsiniz set +H.


19
Tarih genişlemesini tamamen kapatmak, bütün gün duyduğum en iyi tavsiye! Tarih genişleme tehlikeli ve bir Bizans varken çok daha iyi alternatifler (ile artan geçmiş arama Ctrl-Rönizlemenizi & körü körüne komutla uzağa ateş etmeyin böylece komutunu düzenleyelim) !-14Gerçi idi !-12, ayyy, olması oldu o rm -rf *. Dikkatli ol. Geçmiş genişlemesini devre dışı bırak! Eschew !!
aculich

6
En büyük cevap: tarih genişlemesi büyük bir güvenlik riskidir! Unix'inize hazırlanmış bir URL üzerinden saldırmak için kullanılabilir.
dan

@ aculich veya sadece POSIX tarafından belirtilen komutu fc -14kullanın. Ancak, tarih genişlemesi de etkinleştirilmeden bunu yapabildiğiniz doğrudur. Şahsen ben kullanmak !$ve !vive sudo !!ve hatta git add !vi:$yeterince sık geçmişi genişleme etkin bırakarak gerektirecek.
Wildcard,

Bunu benim kabuk RC dosyalarıma ekleyeceğimi düşünüyorum. Bunu sadece temiz bir "numara" olarak kullandım
TonyH

17

Şahsen tek tek tırnak işaretleri yapardım, fakat tamamlama için, bir URL !olduğu için %21, örneğin as olarak kodlayabileceğinizi de not edeceğim curl -v http://example.org/%21132.


13

Bu da yapabilir

curl -v "http://example.org/"'!'"287s87asdjh2/somepath/someresource"
veya
curl -v "http://example.org/"\!"287s87asdjh2/somepath/someresource"

Hangi bash çünkü bash bitişik dizeleri birleştiriyor. Bu yaklaşım özellikle kabuk genişlemesi gereken başka şeyler olduğunda kullanışlıdır, bu nedenle tüm dizge için tek tırnak kullanamazsınız:

curl -v 'http://example.org/!'"287s87asdjh2/${basepath}/someresource"

!karakter, komut satırı isteminde geçmiş açılımları için kullanılır.
Bu nedenle, komut isteminde ancak kabuk komut dosyası dosyalarında bir sorun olabilir.
Gördüğünüz gibi tarih açılımları çift tırnakta bile çalışıyor.


Unix komutları vermenin birçok yolu vardır ve İngilizce cümleler, gerekenden daha fazla karakter kullanır ve gerektiğinden daha kafa karıştırıcı olur. Bu, URL’nin tamamını tek tırnak içine koyarak ilk / kabul / en yüksek oy alan cevaba göre ne kadar üstündür?
G-Man

2
@ G-Man: Bash argümanları oluşturmanın başka bir yolunu gösterir. Bu yöntemin farkında değildim. Yeni şeyler öğrenmede yanlış bir şey yok.
Sahil Singh

@SahilSingh Bu nasıl yeni? İki tanesi çift tırnak işareti ve biri tek tırnak işareti içine alınmış üç dize birleştirir. Burada yuvalama yok.
Raphael

@ G-Man Birbirlerinin yanına 2 tane dizge koyduğunuzda birleştirildikleri açık değildir. printf ("merhaba" "dünya") c de çalışır, ancak printf ("merhaba" 'w') çalışmaz, bu nedenle bash'ın bu tür ifadeleri barındırdığını bilmek benim için yeniydi, ama ben aynı fikirdeyim yarar bakış açısı, bu üstün değildir. Cevabı beğendim, Mark Shust da öyle.
Sahil Singh

2
Bir başka dize açılımları varken @ G-Man Ayrıca yararlıdır gelmez aynı dizede olmasını istiyorum. Bu, iki tür alıntı yapma davranışını ayırmanın kolay bir yoludur.
WAF

7

Aynı problemle karşılaştım ve basit çözümüm değişken kullanmaktı:

E=!  
curl -v "http://example.org/${E}287s87asdjh2/somepath/someresource"

Burada basitliği şudur: (1) Kabuklarda ve komutlarda taşınabilir (2) Kaçış sözdizimi ve ASCII kodlarını bilmek gerekmez.


3

Bash 4.3'ten beri, artık geçmiş genişletme karakterini alıntılamak için çift tırnak kullanabilirsiniz:

$ bash --version
GNU bash, version 4.3...
[...]
$ echo "Hello World!"
Hello World!

Bu dışında çalışmaz echo, echo bu farklı şekilde kendi başına ele görünüyor
phil294

@Blauhirn Bunun yankı ile ilgisi yok, alıntı yapmak ve koştuğunuz bash sürümü ile ilgisi yok.
Flimm

2
Bu cevap yanlış ve silinmesi gerekiyor. Kişisel bashsürümü genişletilmektedir değil patlamayla ilgisi yok, bu örnekte olduğu gerçeği nedeniyle olduğunu !"satırın sonuna" izlemektedir ve bu kadar genişletmeye çalışırken kabuk engeller. Deneyin echo "!Hello World"ve bashcevap vereceğini göreceksiniz bash: !Hello: event not found. Daha fazla bilgi için kılavuza bakın
don_crissti

0

Pencerede git bash kullananlar için @DanielPittman'ın kabul ettiği cevap işe yarıyor. Ancak, ters eğik çizgiyi (\) bir eğik çizgiyle (/) değiştirmelisiniz.

Örneğin, unix'te şöyle bir şey görünür:

curl https://abc.com/services -H 'Authorization: Bearer 111A80BBZZCnS\!ZR412543s'

Pencereler için, bunun gibi bir şey olurdu (yetkilendirme başlığındaki eğik çizgiye odaklanın)

curl https://abc.com/services -H 'Authorization: Bearer 111A80BBZZCnS/!ZR412543s'


Bu pek mantıklı değil. Tek bir argüman alıntı yaptınız, bu nedenle, söz konusu istisnalardan bağımsız olarak, tarihin genişlemesiyle sonuçlanmaz.
Wildcard,

Oh haklısın. Ben sadece bu cevabı gönderdim çünkü Daniel'in cevabını kullanırken (ters eğik çizgi kullanarak) bir hata ortaya çıkıyor.
SamuelDev
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.