eplawless'in kendi cevabı , kendi özel problemini basit ve etkili bir şekilde çözer: "
Tüm argüman listesindeki tüm örnekleri, \"
Bash'in çift tırnaklı bir dizge içinde çift tırnakla değiştirmesi için değiştirir.
Windows komut satırı yorumlayıcısını (komut satırında - genellikle yanlışlıkla "DOS istemi" olarak adlandırılır - veya bir toplu iş dosyasında) kullanarak çift tırnaklı bir dizede çift tırnaktan nasıl kaçılacağıcmd.exe
sorusunu genel olarak yanıtlamak için : PowerShell'e bir göz atmak için aşağıya bakın .
tl; dr :
Sen gerekir kullanmak""
bir dize geçerken bir (nother) için toplu iş dosyası ve olabilecek kullanmak ""
ile oluşturulan uygulamalar ile Microsoft 'ın C / C ++ / NET derleyiciler. (Ki aynı zamanda kabul \"
), Windows üzerinde hangi Python ve node.js içerir :
\"
- tek seçenek olarak - diğer birçok program için gereklidir (örneğin, Ruby, Perl ve hatta Microsoft'un kendi Windows PowerShell'i (!)), ancak KULLANIMI GÜVENLİ DEĞİLDİR :
\"
ne birçok yürütülebilir ve tercümanlar ya gerektirir - Windows PowerShell dahil - geçirilen dizeleri zaman dışarıdan durumunda ya, - , destek Microsoft'un derleyicilerinin alternatif olarak ""
- sonuçta olsa da, bu argüman listesi ayrıştırmak için hedef programa kalmış .
- Misal:
foo.exe "We had 3\" of rain."
- ANCAK,
\"
KOMUTLARIN VE / veya GİRİŞ / ÇIKIŞ YÖNLENDİRMELERİNİN İSTENMEYEN, RASGELE UYGULANMASINA NEDEN OLABİLİR :
- Aşağıdaki karakterler bu riski oluşturur:
& | < >
- Örneğin, aşağıdaki durum,
ver
komutun istenmeden yürütülmesine neden olur ; bir açıklama ve geçici çözüm için sonraki madde işareti için aşağıya bakın:
foo.exe "3\" of snow" "& ver."
- For Windows PowerShell ,
\""
ve "^""
sağlam, ancak sınırlı alternatifler (aşağıda "... PowerShell en CLI arama" bölümüne bakınız).
Kullanmanız gerekiyorsa \"
, sadece 3 güvenli yaklaşım vardır ve bunlar oldukça zahmetlidir : Yardımı için TS'ye şapkanın ucu .
Toplu dosyanızda (muhtemelen seçici ) geciktirilmiş değişken genişletmeyi kullanarak , değişkeni bir değişkende depolayabilir ve sözdizimini kullanarak bir dizge içindeki bu değişkene referans \"
"..."
!var!
verebilirsiniz - bkz. TS'nin yardımcı cevabı .
- Yukarıdaki yaklaşım, külfetli olmasına rağmen, onu metodik olarak uygulayabilme ve herhangi bir girdi ile sağlam bir şekilde çalışabilme avantajına sahiptir .
Yalnızca LITERAL dizelerle - DEĞİŞKENLER İÇERMEYENLER - benzer yöntemsel bir yaklaşım elde ediyor ^
musunuz : kategorik olarak - tüm cmd.exe
meta karakterlerin dışını çıkarın : " & | < >
ve - değişken genişletmeyi de gizlemek istiyorsanız - %
:
foo.exe ^"3\^" of snow^" ^"^& ver.^"
Aksi takdirde, gereken dize hangi bölümlerini tanıyarak dayanarak dize formüle cmd.exe
gördüğü tırnaksız nedeniyle misinterpreting için\"
sınırlayıcılar kapatılması gibi:
içerisinde hazır kabuk meta içeren kısımlar: ^
bunları -escape; Yukarıdaki örneği kullanarak, -escaped &
olması gerekir ^
:
foo.exe "3\" of snow" "^& ver."
bölümlerinde ile %...%
tarzı değişken referanslar : sağlamak cmd.exe
bir onları parçası olarak kabul ettiği "..."
dize ve - değişken değerleri kendileri gömülü değil, dengesiz tırnak yapmak o bile her zaman mümkün değildir .
Arka plan bilgisi için okumaya devam edin.
Arka fon
Not: Bu, kendi deneylerime dayanmaktadır. Yanılıyorsam bana haber ver.
Bash gibi Unix benzeri sistemlerdeki Bash gibi POSIX benzeri kabuklar , bağımsız değişkenleri hedef programa ayrı ayrı iletmeden önce bağımsız değişken listesini (dizeyi) belirtmektedir: diğer genişletmelerin yanı sıra, bağımsız değişken listesini tek tek kelimelere bölerler (sözcük ayırma) ve alıntı karakterlerini sonuçta ortaya çıkan kelimeler (alıntı kaldırma). Hedef program verilir dizi arasında tek tek bağımsız değişken ile, sentaks tırnak çıkarıldı .
Bunun tersine, Windows komut yorumlayıcısı, görünüşe göre argüman listesini belirtmiyor ve alıntı karakterleri de dahil olmak üzere tüm argümanları içeren tek dizeyi basitçe iletiyor. - hedef programa.
Bununla birlikte, bazı ön işlemler tek dizge hedef programa geçmeden önce gerçekleşir: ^
kaçış karakterleri. çift tırnaklı dizelerin dışları kaldırılır (aşağıdaki karakterden kaçarlar) ve önce değişken referanslar (örneğin %USERNAME%
) enterpolasyon yapılır .
Bu nedenle, Unix'ten farklı olarak, hedef programın, argümanlar dizesini ayrıştırmak ve tırnak işaretleri kaldırılarak bağımsız argümanlara bölmek sorumluluğu vardır. Bu nedenle, farklı programlar varsayımsal olarak farklı kaçış yöntemleri gerektirebilir ve tüm programlarla çalışması garanti edilen tek bir kaçış mekanizması yoktur - https://stackoverflow.com/a/4094897/45375 , Windows komut satırı olan anarşi hakkında mükemmel bir arka plan içerir ayrıştırma.
Uygulamada \"
çok yaygındır, ancak yukarıda belirtildiği gibi GÜVENLİ DEĞİLDİR :
Yana cmd.exe
kendisi tanımadığı \"
bir şekilde kaçan çift tırnak, daha sonra misconstrue olarak komut satırında belirteçleri olabilir tırnaksız ve potansiyel olarak yorumlamaktadır komutları ve / veya girdi / çıktı yönlendirmeler .
Özetle: Aşağıdaki, herhangi bir karakter, bir izleyin, bu problem yüzeyleri açılış veya dengesiz \"
:& | < >
; Örneğin:
foo.exe "3\" of snow" "& ver."
cmd.exe
\"
normal bir çift alıntı olarak yanlış yorumlamadan kaynaklanan aşağıdaki simgeleri görür :
"3\"
of
snow" "
- dinlenme:
& ver.
Yana cmd.exe
düşünmektedir & ver.
edilir tırnak içine , bu gibi yorumlayan &
(çalıştırmak için bir komut adından (komut sıralama operatörü), ver.
- .
; ihmal edilir ver
raporları cmd.exe
'ın versiyonu bilgisi).
Genel etki şudur:
- İlk olarak, yalnızca
foo.exe
ilk 3 jetonla çağrılır .
- Ardından komut
ver
yürütülür.
Kazara komutun zarar vermediği durumlarda bile, tüm argümanların kendisine iletilmediği göz önüne alındığında, genel komutunuz tasarlandığı gibi çalışmayacaktır.
Pek çok derleyici / yorumlayıcı YALNIZCA\"
- örneğin GNU C / C ++ derleyicisi, Python, Perl, Ruby, hatta Microsoft'un kendi Windows PowerShell'i çağrıldığında tanırcmd.exe
- ve Windows PowerShell dışında (sınırlamalarla) \""
onlar için basit bir çözüm yoktur. bu soruna.
Esasen, komut satırınızın hangi bölümlerinin ^
alıntılanmamış olarak yanlış yorumlandığını önceden bilmeniz ve seçici & | < >
olarak bu bölümlerdeki tüm örneklerden kaçınmanız gerekir .
Bunun aksine, kullanımı ""
GÜVENLİDİR , ancak ne yazık ki yalnızca Microsoft derleyicisi tabanlı yürütülebilir dosyalar ve toplu iş dosyaları tarafından desteklenir ( toplu iş dosyaları söz konusu olduğunda, yukarıda tartışılan tuhaflıklarla birlikte), bu da PowerShell'i hariç tutar - sonraki bölüme bakın.
PowerShell'in CLI'sini cmd.exe
POSIX benzeri kabuklardan çağırma :
Not: Teklifin PowerShell içinde nasıl işlendiğini görmek için alt bölüme bakın .
Çağrıldığında dışarıdan gelen, örneğin - cmd.exe
:, ister komut satırından veya bir toplu iş dosyasından
PowerShell [Core] v6 + artık""
\"
hem kullanımı güvenli hem de boşlukları koruyan (ek olarak) doğru şekilde tanıyor .
pwsh -c " ""a & c"".length "
kırılmaz ve doğru şekilde verir 6
Windows PowerShell (kimin son sürüm 5.1 olan eski sürüm) tanır sadece \"
ve ayrıca Windows üzerinde """
ve daha sağlam \""
/ '"^""
(olsa bile içten PowerShell kullanımları`
çift tırnak içindeki kaçış karakteri olarak ve aynı zamanda kabul""
- alt bölümüne bakınız):
Arayan Windows PowerShell gelencmd.exe
/ bir toplu iş dosyası:
""
kesintiler , çünkü temelde desteklenmiyor:
powershell -c " ""ab c"".length "
-> hata "Dizede sonlandırıcı eksik"
\"
ve """
çalışma prensip olarak , ama değil güvenli :
powershell -c " \"ab c\".length "
amaçlandığı gibi çalışır: çıktı verir 5
( 2 boşluğa dikkat edin )
- Ama bunun nedeni, güvenli değil
cmd.exe
: meta karakterleri komutunu kırmak, öncelenmedikçe
powershell -c " \"a& c\".length "
sonları nedeniyle, &
gibi kaçtı gerekecekti hangi^&
\""
olan güvenli , ancak normale iç boşluk istenmeyen edilebilir:
powershell -c " \""a& c\"".length "
çıkışlar 4
(!), çünkü 2 boşluk 1'e normalleştirilmiştir.
"^""
özellikle hem güvenli hem de boşlukları koruyan Windows PowerShell için en iyi seçimdir , ancak PowerShell Core ile (Windows'ta)\""
beyaz boşluk normalleştirme ile aynıdır . Bu yaklaşımı keşfettiği için Venryx'e kredi verilir .
powershell -c " "^""a& c"^"".length "
çalışır : kırılmaz - rağmen &
- ve çıktılar 5
, yani doğru şekilde korunmuş boşluk.
PowerShell Çekirdek : pwsh -c " "^""a& c"^"".length "
çalışır , ancak çıkışları 4
, yani normalize boşluk olarak \""
yapar.
Açık Unix gibi platformlar (Linux, MacOS), çağrı zaman PowerShell [Çekirdek] 'in CLI, pwsh
, bir POSIX gibi kabuk gibi bash
:
Sen gerekir kullanmak\"
Ancak hangi güvenli ve boşlukları korunması hem :
$ pwsh -c " \"a& c|\".length"
İlgili bilgi
^
yalnızca tırnaksız dizgelerde kaçış karakteri olarak kullanılabilir - çift tırnaklı dizelerde ^
özel değildir ve değişmez değer olarak değerlendirilir.
- Ikaz : Kullanımı
^
geçirilen parametreleri call
bozuldu açıklamada (bu her iki kullanımları için geçerlidir call
: Başka bir toplu iş dosyası veya ikili çağrılırken ve aynı toplu iş dosyasında bir alt program çağırma):
^
Çift tırnaklı değerlerdeki örnekler, aktarılan değeri değiştirerek açıklanamaz şekilde ikiye katlanır : örneğin, değişken %v%
değişmez değer içeriyorsa a^b
, alt call :foo "%v%"
yordamdaki "a^^b"
( %1
ilk parametre) ' ye ( !) atar :foo
.
- Öncelenmemiş kullanımı
^
ile call
olduğu tamamen kırık ki ^
artık özel karakterler kaçmak için kullanılabilir : örneğin,call foo.cmd a^&b
sessizce (yerine literal geçen sonlarıa&b
dafoo.cmd
olmadan durum olurdu,call
) -foo.cmd
hatta çağrılan asla, en azından Windows üzerinde (!) 7.
Değişmez Kaçan %
özel bir durum olduğunu , ne yazık ki, hangi bir dize belirtilen olmasına göre farklı sözdizimi gerektirir komut satırı vs. bir toplu iş dosyası içinde ; bkz. https://stackoverflow.com/a/31420292/45375
- Kısaca: Bir toplu iş dosyasının içinde kullanın
%%
. Komut satırında, %
öncelenemez, ancak tırnaksız bir dizede ^
bir değişken adının başına, sonuna veya içine bir yerleştirirseniz (örneğin, ), değişken genişletmeyi (enterpolasyon) önleyebilirsiniz; bir değişken referansın parçası olmayan komut satırındaki örnekler değişmez değerler olarak kabul edilir (örneğin, ).echo %^foo%
%
100%
Genellikle, boşluklar ve özel karakterler içerebilen değişken değerlerle güvenle çalışmak için :
- Atama : Hem değişken adını hem de değeri tek bir çift çift tırnak içine alın ; Örneğin, değişkene
set "v=a & b"
değişmez değer atar (aksine, çift tırnak işaretlerini değerin bir parçası yapar). Değişmez örnekleri olduğu gibi çıkar (yalnızca toplu iş dosyalarında çalışır - yukarıya bakın).a & b
%v%
set v="a & b"
%
%%
- Referans : Değerlerinin enterpolasyonlu olmadığından emin olmak için değişken referanslarını çift tırnak ; örneğin,
echo "%v%"
değerine %v%
enterpolasyon ve baskıya tabi değildir "a & b"
(ancak çift tırnakların da değişmez şekilde yazdırıldığını unutmayın). Buna karşılık, echo %v%
edebi geçer a
To echo
,, yorumlayan &
komut sıralama operatörü olarak ve bu nedenle adında bir komut çalıştırmak çalışır b
.
Ayrıca yukarıdaki uyarının ifadeyle ^
birlikte kullanıldığına dikkat edin call
.
- Harici programlar tipik olarak parametrelerin etrafındaki çift tırnak işaretlerini kaldırmaya özen gösterir, ancak belirtildiği gibi, toplu iş dosyalarında bunu kendiniz yapmanız gerekir (örn.,
%~1
1. parametreden çift tırnakları kapatmak için) ve ne yazık ki, doğrudan echo
Değişken değeri ekli çift tırnaklar olmadan aslına sadık bir şekilde yazdırmayı bildiğim bir yol .
- Neil , değerin katıştırılmış çift tırnak işareti olmadığı sürece işe yarayan,
for
tabanlı bir çözüm sunar ; Örneğin:
set "var=^&')|;,%!"
for /f "delims=" %%v in ("%var%") do echo %%~v
cmd.exe
yok değil tanımak tek -quotes dize sınırlayıcı olarak - onlar muamelesi görür ve genellikle gömülü boşluk ile sınırlandırmaktadır dizelerine kullanılamaz; ayrıca, tek tırnak işaretlerine bitişik olan simgeler ve aradaki herhangi bir simge, tarafından alıntılanmamış olarak değerlendirilir cmd.exe
ve buna göre yorumlanır.
- Bununla birlikte, hedef programların nihayetinde kendi argüman çözümlemesini gerçekleştirdiği göz önüne alındığında, Ruby gibi bazı programlar tek tırnaklı dizeleri Windows'ta bile tanır; Buna göre, C / C ++ yürütülebilir, Perl ve Python do not onları tanımak.
Hedef program tarafından desteklense bile, içeriklerinin potansiyel olarak istenmeyen yorumlamalara karşı korunmadığı göz önüne alındığında, tek tırnaklı dizelerin kullanılması tavsiye edilmez cmd.exe
.
PowerShell içinden alıntı yapmak :
Windows PowerShell , olduğundan çok daha gelişmiş bir kabuktur cmd.exe
ve uzun yıllardır Windows'un bir parçasıdır (ve PowerShell Core , PowerShell deneyimini macOS ve Linux'a da getirdi).
PowerShell , alıntı yapma konusunda sürekli olarak dahili olarak çalışır :
- çift tırnaklı dizelerin içinde, çift tırnak işaretlerinden kaçmak için
`"
veya ""
kullanın
- tek tırnaklı dizeler içinde,
''
tek tırnak işaretlerinden kaçmak için kullanın
Bu, PowerShell komut satırında ve parametreleri PowerShell içinden PowerShell betiklerine veya işlevlere iletirken çalışır.
(As bir PowerShell çift tırnak kaçan geçen yukarıda tartışıldığı dışarıdan gerektirir \"
ya, daha sağlam, \""
- başka hiçbir şey işleri).
Ne yazık ki, PowerShell'den harici programları çağırırken , hem PowerShell'in kendi alıntı kurallarına uyma hem de hedef program için kaçma ihtiyacıyla karşı karşıyasınız :
Bu sorunlu davranış da bu cevapta tartışılmış ve özetlenmiştir.
Çift tırnaklı dizeler içinde çift tırnak :
"3`" of rain"
PowerShell'in dahili olarak değişmez değere çevirdiği dizeyi düşünün 3" of rain
.
Bu dizeyi harici bir programa geçirmek istiyorsanız , PowerShell'in yanı sıra hedef programın kaçışını da uygulamanız gerekir ; dizeyi bir C programına geçirmek istediğinizi varsayalım, bu durumda katıştırılmış çift tırnakların şu şekilde önlenmesini bekleyebilirsiniz \"
:
foo.exe "3\`" of rain"
Nasıl Not hem `"
PowerShell mutlu etmek - - ve\
- Hedef programı mutlu etmek için - mevcut olması gerekir.
Aynı mantık, ""
kullanılması gereken bir toplu iş dosyasını çağırmak için de geçerlidir :
foo.bat "3`"`" of rain"
Aksine, çift tırnaklı bir dizeye tek tırnak işaretlerini gömmek için hiçbir çıkış gerekmez .
Tek içeride -quotes tek -quoted dizeleri do not gerektiren ekstra kaçan; düşünün'2'' of snow'
bir PowerShell' temsili olan2' of snow
.
foo.exe '2'' of snow'
foo.bat '2'' of snow'
PowerShell, tek tırnaklı dizeleri hedef programa iletmeden önce çift tırnaklı dizelere çevirir.
Bununla birlikte, PowerShell için çıkış gerektirmeyen tek tırnaklı dizelerdeki çift tırnakların hedef program için yine de öncelenmesi gerekir :
foo.exe '3\" of rain'
foo.bat '3"" of rain'
PowerShell v3 , hedef programa yorumlanmadan herhangi bir şey göndererek ağrının bir kısmını hafifleten , genişletilen -stil ortam değişkeni referansları (örn. ) İçin tasarruf sağlayan, ayrıştırma durdurma sembolü adı verilen sihirli --%
seçeneği sunmuştur ; Örneğin:cmd.exe
%USERNAME%
foo.exe --% "3\" of rain" -u %USERNAME%
Gömülü görülen çıkış kadar Not "
olarak \"
(aynı PowerShell olup, aynı zamanda, sadece hedef program için \`"
yeterlidir).
Ancak bu yaklaşım:
- ortam değişkeni genişletmelerinden kaçınmak için karakterlerin çıkışına izin vermez
%
.
- engellemektedir doğrudan PowerShell değişkenleri ve ifadelerin kullanılması; bunun yerine, komut satırı ilk adımda bir dize değişkeninde oluşturulmalı ve ardından
Invoke-Expression
ikinci adımda çağrılmalıdır .
Bu nedenle, birçok ilerlemesine rağmen, PowerShell harici programları çağırırken kaçmayı çok daha kolay hale getirmedi. Bununla birlikte, tek tırnaklı dizeler için destek sağlamıştır.
Ben icar Unix modeline hiç anahtara Windows dünyasında temelde mümkün olmadığını merak kabuk tüm dizgeciklere ve alıntı kaldırma yapmak tahmin edilebileceği , ön , bağımsız hedef programın ardından hedef programı çağırmak çıkan belirteçleri geçirerek ve .