Escape tanda kutip ganda dalam parameter

109

Di Unix saya bisa lari myscript '"test"'dan saya akan mendapatkannya "test".

Di Windows cmdsaya dapatkan 'test'.

Bagaimana cara melewatkan tanda kutip ganda sebagai parameter? Saya ingin tahu bagaimana melakukan ini secara manual dari cmdjendela sehingga saya tidak perlu menulis program untuk menguji program saya.

Bryan Field
sumber
2
Sudah bertahun-tahun saya tidak menyentuh mesin windows, tetapi bukankah karakter escape standar (backslash \) berfungsi? misalnyamyscript \"test\"
Gazler
Nggak. Saya mendapatkan \ test \. Saya menduga itu karena windows menggunakan \ bukan / jadi garis miring terbalik tidak dapat digunakan sebagai escaper. Tapi saya tidak begitu tahu.
Bryan Field
Idk versi Windows yang Anda gunakan, tetapi \ "berfungsi dengan baik di Windows 7 (Ultimate). Namun, ada cara lain untuk melakukannya, berurusan dengan beberapa tanda kutip (yaitu" "" menjadi "atau semacamnya), tetapi saya tidak bisa mencari tahu kapan dan bagaimana cara kerjanya.
Codesmith
2
kemungkinan duplikat dari Escaping Double Quotes dalam Batch Script
sirdank

Jawaban:

22

Saya tidak dapat mereproduksi gejalanya dengan cepat: jika saya mencoba myscript '"test"'dengan file batch myscript.batyang hanya berisi @echo.%1atau bahkan @echo.%~1, saya mendapatkan semua tanda kutip:'"test"'

Mungkin Anda dapat mencoba karakter melarikan diri ^seperti ini myscript '^"test^"':?

mousio
sumber
3
Lalu mungkin jawaban atas pertanyaan ini dapat membantu Anda lebih jauh?
mousio
2
Ha! Saya tidak pernah menyangka itu wscriptsalah! Serahkan pada Windows :)
Bryan Field
4
Sebenarnya ^ tidak berhasil untuk saya, tetapi \ berhasil, sesuai jawaban ini: stackoverflow.com/questions/2403647/…
kalenjordan
26
Windows: OS di mana globbing, shell expansion, dan parameter unescaping dilakukan oleh executable yang dipanggil, bukan shell. Anda tidak pernah tahu konvensi mana, jika ada, penghargaan yang dapat dieksekusi yang dipanggil.
binki
7
Masukan berharga: blogs.msdn.microsoft.com/twistylittlepassagesallalike/2011/04/… . Tanda sisipan memang merupakan karakter pelarian pilihan cmd.
Peter - Kembalikan Monica
198

Cara lain untuk menghindari tanda kutip (meskipun mungkin tidak disukai), yang saya temukan digunakan di tempat-tempat tertentu adalah dengan menggunakan beberapa tanda kutip ganda . Untuk tujuan membuat kode orang lain terbaca, saya akan menjelaskan.

Berikut seperangkat aturan dasar:

  1. Ketika tidak dibungkus dalam kelompok dikutip ganda, ruang memisahkan parameter:
    program param1 param2 param 3akan melewati empat parameter untuk program.exe:
         param1, param2, param, dan 3.
  2. Sebuah kelompok dikutip ganda mengabaikan spasi sebagai pemisah nilai ketika melewati parameter untuk program:
    program one two "three and more"akan melewati tiga parameter untuk program.exe:
         one, two, dan three and more.
  3. Sekarang untuk menjelaskan beberapa kebingungan:
  4. Kelompok yang muncul berbatasan langsung dengan teks tidak dibungkus dengan tanda kutip ganda bergabung menjadi satu parameter dikutip ganda:
    hello"to the entire"worldbertindak sebagai salah satu parameter: helloto the entireworld.
  5. Catatan: Aturan sebelumnya TIDAK menyiratkan bahwa dua grup yang dikutip ganda dapat muncul berdampingan langsung satu sama lain.
  6. Kutipan ganda apa pun yang langsung mengikuti kutipan penutup diperlakukan sebagai (atau sebagai bagian dari) teks biasa yang tidak terbungkus yang berdekatan dengan grup kutipan ganda, tetapi hanya satu kutipan ganda:
    "Tim says, ""Hi!"""akan bertindak sebagai satu parameter:Tim says, "Hi!"

Jadi, ada tiga jenis tanda kutip ganda yang berbeda: tanda kutip terbuka, tanda kutip penutup, dan tanda kutip yang bertindak sebagai teks biasa.
Inilah rincian baris terakhir yang membingungkan itu:

"buka grup kutipan ganda
T di dalam "" s
saya di dalam "" s
m di dalam "" s
    di dalam "" s - spasi tidak terpisah
ada di dalam "" s
bagian dalam "" s
y di dalam "" s
ada di dalam "" s
, di dalam "" s
    di dalam "" s - spasi tidak terpisah
"tutup grup yang dikutip ganda
"kutipan langsung mengikuti lebih dekat - bertindak sebagai teks biasa yang tidak terbungkus:"
H di luar "" s - bergabung dengan grup berdekatan sebelumnya
aku di luar "" s - ...
! di luar "" s - ...
"buka grup kutipan ganda
"tutup grup kutip ganda
"kutipan langsung mengikuti lebih dekat - bertindak sebagai teks biasa yang tidak terbungkus:"

Dengan demikian, teks secara efektif menggabungkan empat kelompok karakter (satu tanpa ada, bagaimanapun):
Tim says,  adalah yang pertama, dibungkus untuk menghindari spasi
"Hi!adalah yang kedua, tidak dibungkus (tidak ada spasi)
 adalah yang ketiga, kelompok tanda kutip ganda yang tidak membungkus apapun
"adalah yang keempat, kutipan penutup yang terbuka.

Seperti yang Anda lihat, grup kutip ganda yang membungkus tidak ada yang masih diperlukan karena, tanpanya, kutip ganda berikut akan membuka grup kutip ganda alih-alih bertindak sebagai teks biasa.

Dari sini, harus dikenali bahwa oleh karena itu, di dalam dan di luar tanda kutip, tiga tanda kutip ganda bertindak sebagai tanda kutip ganda teks biasa yang tidak dapat dihindari:

"Tim berkata padanya," "" Apa yang terjadi belakangan ini? "" ""

akan mencetak Tim said to him, "What's been happening lately?"seperti yang diharapkan. Oleh karena itu, tiga tanda kutip selalu dapat digunakan dengan andal sebagai pelarian.
Namun, dalam memahaminya, Anda mungkin memperhatikan bahwa empat kutipan di akhir dapat dikurangi menjadi hanya dua karena secara teknis menambahkan grup kutipan ganda kosong yang tidak perlu.

Berikut beberapa contoh untuk menutupnya:

Program ab REM mengirimkan (a) dan (b)
program "" "a" "" REM mengirim ("a")
program "" "a b" "" REM mengirim ("a) dan (b")
program "" "" Halo, "" "kata Mike." REM mengirim ("Halo," kata Mike.)
program "" a "" b "" c "" d "" REM mengirim (abcd) karena grup "" tidak membungkus apa pun
program "hello to" "" quotes "" REM mengirim (halo ke "quotes")
program "" "" hello world "" REM mengirim ("hello world")
program "" "halo" dunia "" REM mengirim ("halo dunia")
program "" "halo" dunia "" REM mengirim ("halo) dan (dunia")
program "halo" "dunia" "" REM mengirim (halo "dunia")
program "halo" "" dunia "" REM mengirim (halo "dunia")

Catatan terakhir: Saya tidak membaca semua ini dari tutorial mana pun - saya mendapatkan semuanya dengan bereksperimen. Oleh karena itu, penjelasan saya mungkin tidak benar secara internal. Meskipun demikian, semua contoh di atas mengevaluasi seperti yang diberikan, dengan demikian memvalidasi (tetapi tidak membuktikan) teori saya.

Saya menguji ini pada Windows 7, 64bit hanya menggunakan panggilan * .exe dengan parameter passing (bukan * .bat, tetapi saya kira itu berfungsi sama).

Codesmith
sumber
11
+1, tetapi perhatikan bahwa perilaku ini tergantung pada aplikasinya. Di Windows, setiap aplikasi mem-parsing parameter baris perintahnya sendiri. Saya yakin perilaku yang Anda gambarkan adalah perilaku pustaka C standar Microsoft, yang menurut saya juga diduplikasi oleh sebagian besar kompiler Windows C lainnya.
Harry Johnston
3
Beberapa kesalahan dalam pengecualian terakhir Anda. program "" "ab" "" -> ("ab"), program "hello to" "" quotes "" -> (halo untuk "quotes), program" "" "hello world" "-> (" Halo) (dunia), program "" "halo" dunia "" -> ("halo) (dunia), program" "" halo "dunia" "-> (" halo dunia), program "halo" "" dunia "" - > (halo "dunia)
Thomson
46
... Yang bisa saya katakan adalah, file batch Windows mengalami masalah. Ini adalah kutipan pelarian , demi Tuhan; itu tidak harus menjadi semacam ilmu roket.
James Ko
4
@JamesKo Saya sangat setuju. Absurditas misterius dan inkonsistensi baris perintah Windows tidak pernah gagal membuat saya marah. Siapa yang mendesain sampah ini? Oh, waktu terbuang percuma selama bertahun-tahun! Unix sangat mudah dan sangat masuk akal jika dibandingkan.
Carlos A. Ibarra
24

Coba ini:

myscript """test"""

"" escape to a single "di parameter.

smwikipedia
sumber
1
Itu tidak sepenuhnya benar. Coba myscript """test test"""dan tidak berhasil (parameter pertama diserahkan sebagai "test. Sebenarnya, Anda memerlukan tiga tanda kutip: myscript """"test test""Meskipun demikian, kutipan ketiga di akhir dapat dilewati.
Ignitor
bagaimana jika saya perlu menghapus semua tanda kutip di sini dan menempatkan nilai parameter dalam string yang digunakan dalam filter kueri pemilihan? Bisakah seseorang membantu?
SFDC_Learner
2
Mungkin tidak tepat untuk pertanyaan ini, tetapi ini membantu saya ketika saya perlu beralih char **argvdari peluncur C saya ke proses lain menggunakan fungsi seperti spawnatau exec. Terima kasih. :-)
virgo47
2

Dokumen kedua yang dikutip oleh Peter Mortensen dalam komentarnya atas jawaban Codesmith membuat segalanya menjadi lebih jelas bagi saya. Dokumen itu ditulis oleh windowsinspired.com. Tautan berulang: Cara yang Lebih Baik Untuk Memahami Quoting dan Escaping dari Argumen Baris Perintah Windows .

Beberapa trial and error lebih lanjut mengarah pada pedoman berikut:

Hindari setiap kutipan ganda "dengan tanda sisipan ^. Jika Anda ingin karakter lain dengan arti khusus untuk perintah Windows shell (misalnya, <, >, |, &) harus ditafsirkan sebagai karakter biasa, bukan, lalu melarikan diri mereka dengan sebuah tanda sisipan, juga.

Jika Anda ingin program Anda foo untuk menerima teks baris perintah "a\"b c" > ddan mengarahkan output ke file out.txt , kemudian memulai program Anda sebagai berikut dari perintah Windows shell:

foo ^"a\^"b c^" ^> d > out.txt

Jika foo menafsirkan \"sebagai tanda kutip ganda literal dan mengharapkan tanda kutip ganda yang tidak lolos untuk membatasi argumen yang menyertakan spasi, maka foo menafsirkan perintah tersebut sebagai menentukan satu argumen a"b c, satu argumen >, dan satu argumen d.

Jika sebaliknya foo menafsirkan tanda petik ganda ""sebagai tanda petik ganda literal, maka mulailah program Anda sebagai

foo ^"a^"^"b c^" ^> d > out.txt

Wawasan utama dari dokumen yang dikutip adalah bahwa, ke shell perintah Windows, tanda kutip ganda yang tidak dapat dihindarkan memicu peralihan antara dua kemungkinan status.

Beberapa trial and error lebih lanjut menyiratkan bahwa dalam keadaan awal, pengalihan (ke file atau pipa) dikenali dan tanda sisipan ^lolos dari tanda kutip ganda dan tanda sisipan dihapus dari input. Di negara bagian lain, pengalihan tidak dikenali dan tanda sisipan tidak lolos dari tanda kutip ganda dan tidak dihapus. Mari kita lihat keadaan ini masing-masing sebagai 'di luar' dan 'di dalam'.

Jika Anda ingin mengalihkan keluaran dari perintah Anda, maka shell perintah harus dalam keadaan luar saat mencapai pengalihan, jadi harus ada jumlah genap dari tanda kutip ganda yang tidak lolos (dengan tanda sisipan) sebelum pengalihan. foo "a\"b " > out.txttidak akan berfungsi - shell perintah meneruskan keseluruhan "a\"b " > out.txtke foo sebagai argumen baris perintah gabungannya, alih-alih hanya "a\"b "meneruskan dan mengarahkan keluaran ke out.txt .

foo "a\^"b " > out.txtjuga tidak akan berfungsi, karena tanda sisipan ^ditemukan di dalam keadaan di mana itu adalah karakter biasa dan bukan karakter melarikan diri, jadi "a\^"b " > out.txtditeruskan ke foo .

Satu-satunya cara yang (mudah-mudahan) selalu berhasil adalah dengan menjaga shell perintah selalu dalam keadaan luar, karena dengan demikian pengalihan berfungsi.

Jika Anda tidak memerlukan pengalihan (atau karakter lain dengan arti khusus ke shell perintah), Anda dapat melakukannya tanpa tanda sisipan. Jika foo diartikan \"sebagai kutipan ganda literal, maka Anda dapat menyebutnya sebagai

foo "a\"b c"

Kemudian foo menerima "a\"b c"sebagai teks argumen gabungannya dan dapat menafsirkannya sebagai satu argumen yang sama dengan a"b c.

Sekarang - akhirnya - ke pertanyaan awal. myscript '"test"'dipanggil dari shell perintah Windows lolos '"test"'ke myscript . Rupanya myscript menafsirkan tanda kutip tunggal dan ganda sebagai pemisah argumen dan menghapusnya. Anda perlu mencari tahu apa yang diterima myscript sebagai kutipan ganda literal dan kemudian tentukan itu dalam perintah Anda, gunakan ^untuk keluar dari karakter apa pun yang memiliki arti khusus ke shell perintah Windows. Mengingat itu myscriptjuga tersedia di Unix, mungkin berhasil \". Mencoba

myscript \^"test\^"

atau, jika Anda tidak membutuhkan pengalihan,

myscript \"test\"
Louis Strous
sumber
TERIMA KASIH! Saya memukuli kepala saya di dinding mencoba menjalankan vbscript dengan teks prompt cmd digema ke dalam teks prompt cmd - Saya mewarisi ini - dan tidak dapat menemukan cara untuk menghindari tanda kutip.
PopeDarren
0

Saya menelepon PowerShell dari cmd, dan memberikan tanda kutip dan tidak ada pelarian di sini yang berhasil. Aksen kubur bekerja untuk menghindari tanda kutip ganda pada pro permukaan Win 10 ini.

>powershell.exe "echo la`"" >> test
>type test
la"

Di bawah ini adalah keluaran yang saya dapatkan untuk karakter lain agar lolos dari kutipan ganda:

la\
la^
la
la~

Menggunakan kutipan lain untuk menyela kutipan tidak menghasilkan kutipan. Seperti yang Anda lihat, karakter itu sendiri diketik, tetapi tidak luput dari tanda kutip ganda.

Zimba
sumber