Toplu Komut Dosyasında Çift Tırnaktan Kaçış


96

Toplu iş dosyamın parametrelerindeki tüm çift tırnakları kaçan çift tırnaklarla değiştirmeye nasıl gidebilirim? Bu, tüm komut satırı parametrelerini dize içinde genişleten geçerli toplu iş dosyam:

@echo off
call bash --verbose -c "g++-linux-4.1 %*"

Daha sonra, bir Linux çapraz derleyicisini çalıştırarak Cygwin'in bash'ına bir çağrı yapmak için bu dizeyi kullanır. Ne yazık ki, toplu iş dosyama şu gibi parametreler alıyorum:

"launch-linux-g++.bat" -ftemplate-depth-128 -O3 -finline-functions 
-Wno-inline -Wall  -DNDEBUG   -c 
-o "C:\Users\Me\Documents\Testing\SparseLib\bin\Win32\LinuxRelease\hello.o" 
"c:\Users\Me\Documents\Testing\SparseLib\SparseLib\hello.cpp"

İletilen ilk yolun etrafındaki ilk alıntı, dizenin GCC'ye iletilmesinden önce erken sonlandırılması ve geri kalan parametrelerin doğrudan bash'a geçirilmesi (ki bu şaşırtıcı bir şekilde başarısız olur).

Parametreleri tek bir dizede birleştirip sonra tırnak işaretlerinden kaçabilirsem, iyi çalışması gerektiğini hayal ediyorum, ancak bunu nasıl yapacağımı belirlemekte zorlanıyorum. Kimse biliyor mu?

Yanıtlar:


106

Toplu komut kaçış karakteridir ^. Ancak çift tırnaklı dizeler için tırnak işaretlerini ikiye katlayın:

"string with an embedded "" character"

5
iki katına tırnak vermedi değil benim için çalışır, ancak ^ bir şampiyon gibi çalıştı.
davenpcj

27
^yalnızca tırnaksız dizelerdeki çıkış karakteridir ; çift ​​tırnaklı dizelerde değişmez olarak değerlendirilir. Unix (POSIX benzeri) kabuklardan farklı olarak, çift ​​tırnaklı bir dizge içindeki çift tırnakların cmd.exeHİÇBİR standardize edilmiş kabuk muamelesi sunmaz ve yorum, çalıştırılan programa bırakılır (sonraki açıklamada devam eder).
mklement0

9
(önceki yorumdan devam ediyor) Pratikte, çoğu çalıştırılabilir / betik yorumlayıcısı "karakter bekleme C kuralını uygular . \"çift ​​tırnaklı bir dizenin içinde olduğu gibi kaçışılacak (en azından C / C ++, Python, Perl, Ruby için geçerlidir). Buna karşılık, ""sadece tanınan azınlık grup dosyalarına geçirilen parametreler,: vakaların "" olduğu bir olarak kabul gömülü çift tırnak, ancak olduğu gibi muhafaza tekabül içinde %<n>bile çıkardıktan sonra, parametre çevreleyen çift tırnak %~<n>. Python da"" bir alternatif olarak nezaketle tanır \".
mklement0

91

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 :

    • Misal: foo.bat "We had 3"" of rain."

    • Aşağıdakiler yalnızca toplu iş dosyaları için geçerlidir:

      • ""cmd.exeçift ​​tırnaklı dizenin tamamını tek bir argüman olarak ele almak için komut yorumlayıcısını ( ) elde etmenin tek yoludur .

      • Ne yazık ki, sadece çevreleyen çift tırnaklar (her zamanki gibi) değil, aynı zamanda çift çıkışlı olanlar da tutulur, bu nedenle amaçlanan dizeyi elde etmek iki aşamalı bir süreçtir; Örneğin, çift tırnaklı dizenin 1. bağımsız değişken olarak aktarıldığını varsayarsak %1:

      • set "str=%~1"çevreleyen çift tırnakları kaldırır; set "str=%str:""="%"daha sonra, çift tırnak işaretlerini tek olanlara dönüştürür.
        Değerlerin istenmeyen yorumlanmasını önlemek için atama bölümlerinin etrafındaki çift tırnak işaretlerini kullandığınızdan emin olun.

  • \"- 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, verkomutun 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.exegö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.exebir 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.exekendisi 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.exedüşü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 verraporları cmd.exe'ın versiyonu bilgisi).
Genel etki şudur:

  • İlk olarak, yalnızca foo.exeilk 3 jetonla çağrılır .
  • Ardından komut veryü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.exePOSIX 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" # OK: 5

İ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 callbozuldu 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"( %1ilk parametre) ' ye ( !) atar :foo.
      • Öncelenmemiş kullanımı ^ile callolduğu tamamen kırık ki ^artık özel karakterler kaçmak için kullanılabilir : örneğin,call foo.cmd a^&bsessizce (yerine literal geçen sonlarıa&bdafoo.cmdolmadan durum olurdu,call) -foo.cmdhatta ç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 aTo 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., %~11. parametreden çift tırnakları kapatmak için) ve ne yazık ki, doğrudan echoDeğ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, fortabanlı bir çözüm sunar ; Örneğin:
        set "var=^&')|;,%!" for /f "delims=" %%v in ("%var%") do echo %%~v
  • cmd.exeyok 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.exeve 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.exeve 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-Expressionikinci 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 .


Güzel açıklama! Ama ... pek Literal use of ^ in double-quoted strings can, be problematic when applying ~ ...değil. Tilde, yalnızca mevcut olduğunda dış tırnak işaretlerini kaldırır. Düzeltme işaretlerinin kaybolması, işlemenin kendisinin bir sorunudur. Normalde a bunu set "param=%~1"çözer.
15'15

Teşekkürler @jeb, sorun gerçekten kullanımına özgü değil ~- Cevabımı yeni anlayışımı yansıtacak şekilde güncelledim - lütfen bir sorunla karşılaşırsanız yorum yapın. ^Parametreleri bir callifadeye aktardığınızda bunun ikiye katlanmasının otomatik olarak gerçekleşmesi için bir açıklamanız var mı?
mklement0

3
Sadece MS'teki birinin bunun harika olduğunu düşündüğünü tahmin edebilirim. İkiye katlanan düzeltme işaretlerinin ikinci ayrıştırma aşamasında otomatik olarak kaldırılacağı. Ancak bu büyük bir başarısızlıktı çünkü tırnak içinde çalışmıyor ve herhangi bir özel karakterin kaçmasını etkili bir şekilde engelliyor. Gibi call echo cat^^&dogtek başına düzeltme imi herhangi bir miktar ile solveable değil
Jeb

Teşekkürler, @jeb, ben bile düşünmemiştik tırnaksız kullanımı ^ile callsize işaret olarak, bozuk bir sistem olan,. Görünüşe göre call echo cat^&dog( ^uygun şekilde kaçan tek &) hedef komutu ( echo) asla çağrılmaz (!) - tüm komut sessizce başarısız olur. Cevabı buna göre güncelledim.
mklement0

Güzel Cevap. Bununla birlikte, ""kaçmış olarak tavsiye etmem "ama her zaman \"(cmd içinden kullanmanın daha az tehlikeli bir yolu için cevabıma bakın). Ben tanımlar o herhangi bir resmi belgelerine bilmiyorum ""bir şekilde alıntı kurtuldu, ama söz en az 2 \": .NET ve VS . Yanlış belgelenmesine rağmen, Win32 api de bu kuralları takip eder.
TS

24

Google sonunda cevabı buldu. Toplu işteki dize değişiminin sözdizimi şudur:

set v_myvar=replace me
set v_myvar=%v_myvar:ace=icate%

Hangi "beni kopyala" yı üretir. Senaryom şimdi şöyle görünüyor:

@echo off
set v_params=%*
set v_params=%v_params:"=\"%
call bash -c "g++-linux-4.1 %v_params%"

Tüm örneklerini "ile değiştiren \", bash için uygun şekilde kaçtı.


9

Mklement0'ın mükemmel cevabına ek olarak :

Hemen hemen tüm yürütülebilir kabul \"kaçan bir şekilde ". Ancak cmd'de güvenli kullanım neredeyse yalnızca GECİKME GENİŞLETME kullanılarak mümkündür.
Belirli bir "sürece açık bir şekilde hazır bilgi göndermek için , \"bir ortam değişkenine atayın ve ardından bir teklif iletmeniz gerektiğinde bu değişkeni kullanın. Misal:

SETLOCAL ENABLEDELAYEDEXPANSION
set q=\"
child "malicious argument!q!&whoami"

Not SETLOCAL ENABLEDELAYEDEXPANSION, yalnızca toplu iş dosyalarında çalışıyor gibi görünüyor. Etkileşimli bir oturumda GECİKME GENİŞLEME elde etmek için başlayın cmd /V:ON.

Toplu dosyanız DELAYEDEXPANSION ile çalışmıyorsa, geçici olarak etkinleştirebilirsiniz:

::region without DELAYEDEXPANSION

SETLOCAL ENABLEDELAYEDEXPANSION
::region with DELAYEDEXPANSION
set q=\"
echoarg.exe "ab !q! & echo danger"
ENDLOCAL

::region without DELAYEDEXPANSION

Siz öncelenir tırnak içeren bir değişken dinamik içerik geçmek istiyorsanız ""size yerini alabilir ""ile \"genişlemesine:

SETLOCAL ENABLEDELAYEDEXPANSION
foo.exe "danger & bar=region with !dynamic_content:""=\"! & danger"
ENDLOCAL

Bu değiştirme, %...%stil genişletme ile güvenli değildir !

OP durumunda bash -c "g++-linux-4.1 !v_params:"=\"!"güvenli versiyondur.


Herhangi bir nedenle GECİKMELİ GENİŞLETMENİN geçici olarak etkinleştirilmesi bile bir seçenek değilse, okumaya devam edin:

\"Cmd içinden kullanmak , sadece bazen yerine özel karakterlerden her zaman kaçmak gerektiğinde biraz daha güvenlidir. (Tutarlıysa imleci unutmak daha az olasıdır ...)

Bunu başarmak için, herhangi bir alıntıdan önce şapka işareti ( ^") bulunur, alt sürece ulaşması gereken tırnakların ek olarak bir boşluk ( \^") ile öncelenmesi gerekir . TÜM kabuk meta karakterlerinin de öncelenmesi gerekir ^, örneğin &=> ^&; |=> ^|; >=> ^>; vb.

Misal:

child ^"malicious argument\^"^&whoami^"

Kaynak: Herkes komut satırı argümanlarını yanlış şekilde alıntılıyor , bkz. "Daha iyi bir alıntı yapma yöntemi"


Dinamik içeriği iletmek için aşağıdakilerin sağlanması gerekir:
Komutun değişkeni içeren kısmı tarafından "alıntılanmış" olarak kabul edilmelidir cmd.exe(Değişken tırnak içerebiliyorsa bu imkansızdır - yazmayın%var:""=\"% ). Bunu başarmak için ", değişkenden önceki son ve değişkenden "sonraki ilk ^-escaped değildir . Bu ikisi arasındaki cmd-metakarakterlerin "öncelenmemesi gerekir. Misal:

foo.exe ^"danger ^& bar=\"region with %dynamic_content% & danger\"^"

%dynamic_content%Eşsiz alıntılar içerebiliyorsa , bu güvenli değildir .


Anladım teşekkürler. Evet, kategorik ^-escaping tüm sağlam meta karakterler işler ve daha yöntemli uygulanabilir (henüz açıkça seçtiğiniz vücut kesiminde bir kraliyet ağrı). Cevabımı buna göre güncelledim (ve size kredi verdim).
mklement0

@ mklement0 Teşekkürler! Evet, gerçekten bir acı. Can sıkıcı ve bir meta karakteri unutmak hala çok kolay (bu yüzden çoğunlukla !q!yolu kullanıyorum). Not: "Do: Yakın diyorsunuz top: Cevabınız son düzenleme sonrasında hafif tutarsız değil kullanmak ^"". Daha sonra ^"geçici çözümün bir parçası olarak kullanırsınız . Belki her iki yolu da açıklayabilirsin? (1) Tüm meta karakterlerden kaçış (daha metodik olarak) / (2) " foo.exe ^"danger ^& bar=\"%dynamic_content%\"^"alıntılanmamış " bölgelerdeki meta karakterlerden seçmeli olarak kaçış (bazen dinamik içeriği geçirmek için gereklidir, örneğin - bu şekilde değişken cmd için alıntılanır)
TS

İyi nokta, teşekkürler - cevap güncellendi. Ayrıca MS derleyicisinin \"ve "". Daha kapsamlı değişken tabanlı yaklaşım için cevabınıza bağladım. Şimdi mantıklı olup olmadığını bana bildirin.
mklement0

1
@ mklement0 Cevabınız her zaman mantıklı geldi :-) Sadece olası iyileştirmeler için bazı fikirler vermek istedim. Cevabıma hakkındaki örneği de ekledim %dynamic_content%. Yeterince ayrıntılı olduğunu mu düşünüyorsunuz yoksa daha fazla açıklamam gerekiyor mu?
TS

3
Harika, haber verdiğin için teşekkürler. Yerelleştirmek için iyi bir fikir setlocal delayedexpansion, ancak bloğu endlocal(argüman yok) ile sonlandırmalısınız . Dürüst olmak gerekirse, başım dönmeye başladı, Özüne baktı. Burada gerçekten uç vakalarla uğraşıyoruz ve bence gelecekteki okuyucular ihtiyaç duydukları her şeyi iki cevabımız arasında bulacaklar.
mklement0

0

Dize zaten tırnak içindeyse, eylemini geçersiz kılmak için başka bir alıntı kullanın.

echo "Insert tablename(col1) Values('""val1""')" 

-3

Örneğin, Unreal motor Otomasyon aracı toplu iş dosyasından çalıştırılır - bu benim için çalıştı

örneğin: -cmdline = "-Mesaj" -device = cihaz -addcmdline = "- SessionId = oturum -SessionOwner = 'owner' -SessionName = 'Build' -dataProviderMode = local -LogCmds = 'LogCommodity OFF' -execcmds = 'otomasyon listesi ; yeniden test testleri + + T1 + T2 ile ayrılmış; '"-çalıştırmadan çıkın

Umarım bu birine yardımcı olur, benim için çalıştı.


Çalışmalarınızdan uzun ve çoğunlukla alakalı olmayan bir kopya yapıştırmak yerine, paylaşmaya çalıştığınız kavramı net bir örnek haline getirmeye çalışın.
run_the_race
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.