Kami melakukan percobaan untuk menyelidiki tata bahasa skrip batch. Kami juga menyelidiki perbedaan antara mode batch dan command line.
Parser Garis Batch:
Berikut ini adalah ikhtisar singkat fase dalam parser baris file batch:
Fase 0) Baca Baris:
Fase 1) Ekspansi Persen:
Fase 2) Memproses karakter khusus, tokenize, dan membangun blok perintah yang di-cache: Ini adalah proses kompleks yang dipengaruhi oleh hal-hal seperti kutipan, karakter khusus, pembatas token, dan lolos caret.
Fase 3) Gema perintah terurai hanya jika blok perintah tidak dimulai @
, dan ECHO AKTIF pada awal langkah sebelumnya.
Fase 4) UNTUK %X
ekspansi variabel: Hanya jika perintah FOR aktif dan perintah setelah DO sedang diproses.
Fase 5) Ekspansi Tertunda: Hanya jika ekspansi yang tertunda diaktifkan
Fase 5.3) Pemrosesan pipa: Hanya jika perintah ada di kedua sisi pipa
Fase 5.5) Jalankan Redirection:
Fase 6) Pemrosesan CALL / Penggandaan Caret: Hanya jika token perintahnya adalah CALL
Tahap 7) Jalankan: Perintah dijalankan
Berikut detail untuk setiap fase:
Perhatikan bahwa fase yang dijelaskan di bawah ini hanya model cara kerja pengurai batch. Internal cmd.exe yang sebenarnya mungkin tidak mencerminkan fase-fase ini. Tetapi model ini efektif untuk memprediksi perilaku skrip batch.
Fase 0) Jalur Baca : Baca jalur input terlebih dahulu <LF>
.
- Saat membaca baris yang akan diuraikan sebagai perintah,
<Ctrl-Z>
(0x1A) dibaca sebagai <LF>
(LineFeed 0x0A)
- Ketika GOTO atau CALL membaca baris saat memindai label:
<Ctrl-Z>
,, diperlakukan sebagai dirinya sendiri - itu tidak dikonversi menjadi<LF>
Fase 1) Ekspansi Persen:
- Ganda
%%
digantikan oleh satu%
- Perluasan argumen (
%*
, %1
,%2
, dll)
- Perluasan
%var%
, jika var tidak ada ganti saja dengan apa-apa
- Garis terpotong pada awalnya
<LF>
tidak dalam %var%
ekspansi
- Untuk penjelasan lengkap, baca paruh pertama ini dari dbenham Utas yang sama: Persen Fase
Fase 2) Memproses karakter khusus, tokenize, dan membangun blok perintah yang di-cache: Ini adalah proses kompleks yang dipengaruhi oleh hal-hal seperti kutipan, karakter khusus, pembatas token, dan lolos caret. Berikut ini adalah perkiraan proses ini.
Ada konsep yang penting di seluruh fase ini.
- Token hanyalah serangkaian karakter yang diperlakukan sebagai satu unit.
- Token dipisahkan oleh pembatas token. Pembatas token standar adalah
<space>
<tab>
;
,
=
<0x0B>
<0x0C>
dan<0xFF>
Pembatas token berurutan diperlakukan sebagai satu - tidak ada token kosong antara pembatas token
- Tidak ada pembatas token dalam string yang dikutip. Seluruh string yang dikutip selalu diperlakukan sebagai bagian dari token tunggal. Token tunggal dapat terdiri dari kombinasi string yang dikutip dan karakter yang tidak dikutip.
Karakter berikut mungkin memiliki arti khusus dalam fase ini, tergantung pada konteks: <CR>
^
(
@
&
|
<
>
<LF>
<space>
<tab>
;
,
=
<0x0B>
<0x0C>
<0xFF>
Lihatlah setiap karakter dari kiri ke kanan:
- Jika
<CR>
kemudian menghapusnya, seolah-olah itu tidak pernah ada (kecuali untuk perilaku pengalihan aneh )
- Jika sebuah tanda sisipan (
^
), karakter berikutnya akan keluar, dan tanda tanda untuk melarikan diri dihapus. Karakter yang lolos kehilangan semua makna khusus (kecuali untuk <LF>
).
- Jika kutipan (
"
), ganti bendera tanda kutip. Jika tanda kutip aktif, maka hanya "
dan<LF>
istimewa. Semua karakter lain kehilangan makna khusus mereka sampai kutipan berikutnya mematikan bendera kutipan. Tidak mungkin untuk menghindari kutipan penutup. Semua karakter yang dikutip selalu dalam token yang sama.
<LF>
selalu mematikan bendera kutipan. Perilaku lain bervariasi tergantung pada konteks, tetapi kutipan tidak pernah mengubah perilaku <LF>
.
- Lolos
<LF>
<LF>
dilucuti
- Karakter selanjutnya lolos. Jika pada akhir buffer baris, maka baris berikutnya dibaca dan diproses oleh fase 1 dan 1.5 dan ditambahkan ke yang sekarang sebelum keluar dari karakter berikutnya. Jika karakter selanjutnya adalah
<LF>
, maka itu diperlakukan sebagai literal, artinya proses ini tidak rekursif.
- Tidak terhindar dari
<LF>
tanda kurung
<LF>
dilucuti dan penguraian garis saat ini dihentikan.
- Setiap karakter yang tersisa di buffer baris diabaikan saja.
- Tidak terhapus di
<LF>
dalam blok yang di-tanda kurung dalam IN
<LF>
dikonversi menjadi <space>
- Jika pada akhir buffer baris, maka baris berikutnya dibaca dan ditambahkan ke yang sekarang.
- Tidak terhapus di
<LF>
dalam blok perintah yang di-kurung
<LF>
dikonversi menjadi <LF><space>
, dan <space>
diperlakukan sebagai bagian dari baris berikutnya dari blok perintah.
- Jika pada akhir buffer baris, maka baris berikutnya dibaca dan ditambahkan ke spasi.
- Jika salah satu karakter khusus
&
|
<
atau >
, pisahkan garis pada titik ini untuk menangani pipa, menyatukan perintah, dan pengalihan.
- Dalam kasus pipa (
|
), setiap sisi adalah perintah terpisah (atau blok perintah) yang mendapat penanganan khusus dalam fase 5.3
- Dalam kasus
&
, &&
atau ||
Rangkaian perintah, setiap sisi Rangkaian diperlakukan sebagai perintah yang terpisah.
- Dalam kasus
<
, <<
, >
, atau >>
pengalihan, pengalihan klausa diurai, sementara dihapus, dan kemudian ditambahkan ke akhir dari perintah saat ini. Klausa pengalihan terdiri dari digit pegangan file opsional, operator pengalihan, dan token tujuan pengalihan.
- Jika token yang mendahului operator redirection adalah digit unescaped tunggal, maka digit menentukan pegangan file yang akan diarahkan. Jika token pegangan tidak ditemukan, maka output redirection default ke 1 (stdout), dan input redirection default ke 0 (stdin).
- Jika token pertama untuk perintah ini (sebelum memindahkan redirection ke akhir) dimulai dengan
@
, maka @
memiliki arti khusus. ( @
tidak spesial dalam konteks lain)
- Spesial
@
dihapus.
- Jika ECHO AKTIF, maka perintah ini, bersama dengan perintah gabungan berikut di baris ini, dikecualikan dari gema fase 3. Jika
@
sebelum pembukaan (
, maka seluruh blok yang dikurung dikecualikan dari gema fase 3.
- Tanda kurung proses (memberikan pernyataan majemuk melintasi beberapa baris):
- Jika parser tidak mencari token perintah, maka
(
tidak khusus.
- Jika parser sedang mencari token perintah dan menemukan
(
, kemudian mulai pernyataan majemuk baru dan menambah penghitung tanda kurung
- Jika penghitung tanda kurung> 0 maka
)
akhiri pernyataan majemuk dan kurangi penghitung tanda kurung.
- Jika ujung garis tercapai dan penghitung tanda kurung> 0 maka baris berikutnya akan ditambahkan ke pernyataan gabungan (dimulai lagi dengan fase 0)
- Jika penghitung tanda kurung adalah 0 dan parser sedang mencari perintah, maka
)
fungsinya mirip dengan REM
pernyataan selama itu segera diikuti oleh pembatas token, karakter khusus, baris baru, atau akhir file
- Semua karakter khusus kehilangan artinya kecuali
^
(penggabungan baris dimungkinkan)
- Setelah akhir baris logis tercapai, seluruh "perintah" dibuang.
- Setiap perintah diuraikan menjadi serangkaian token. Token pertama selalu diperlakukan sebagai token perintah (setelah khusus
@
telah dilucuti dan pengalihan dipindahkan ke akhir).
- Pembatas token terkemuka sebelum token perintah dilucuti
- Saat parsing token perintah,
(
berfungsi sebagai pembatas token perintah, selain sebagai pembatas token standar
- Penanganan token berikutnya tergantung pada perintah.
- Sebagian besar perintah hanya menggabungkan semua argumen setelah token perintah menjadi token argumen tunggal. Semua pembatas token argumen dipertahankan. Opsi argumen biasanya tidak diuraikan sampai fase 7.
- Tiga perintah mendapatkan penanganan khusus - IF, FOR, dan REM
- JIKA dibagi menjadi dua atau tiga bagian berbeda yang diproses secara independen. Kesalahan sintaksis dalam konstruksi IF akan menghasilkan kesalahan sintaksis fatal.
- Operasi perbandingan adalah perintah aktual yang mengalir hingga fase 7
- Semua opsi IF sepenuhnya diuraikan dalam fase 2.
- Pembatas token berturut-turut runtuh ke dalam satu ruang.
- Bergantung pada operator pembanding, akan ada satu atau dua token nilai yang diidentifikasi.
- Blok perintah True adalah kumpulan perintah setelah kondisi, dan diuraikan seperti blok perintah lainnya. Jika ELSE akan digunakan, maka blok True harus di-kurung.
- Blok perintah False opsional adalah serangkaian perintah setelah ELSE. Sekali lagi, blok perintah ini diuraikan secara normal.
- Blok perintah Benar dan Salah tidak secara otomatis mengalir ke fase berikutnya. Proses selanjutnya mereka dikendalikan oleh fase 7.
- FOR dibagi menjadi dua setelah DO. Kesalahan sintaksis dalam konstruksi FOR akan menghasilkan kesalahan sintaksis yang fatal.
- Bagian melalui DO adalah perintah UNTUK iterasi aktual yang mengalir sepanjang fase 7
- Semua opsi UNTUK sepenuhnya diuraikan dalam fase 2.
- Klausa IN tanda kurung memperlakukan
<LF>
sebagai <space>
. Setelah klausa IN diuraikan, semua token digabungkan bersama untuk membentuk token tunggal.
- Pembatas token yang tidak terhapus / tidak dikutip secara otomatis runtuh ke dalam satu ruang di seluruh perintah FOR melalui DO.
- Bagian setelah DO adalah blok perintah yang diurai secara normal. Pemrosesan selanjutnya dari blok perintah DO dikendalikan oleh iterasi pada fase 7.
- REM terdeteksi dalam fase 2 diperlakukan secara dramatis berbeda dari semua perintah lainnya.
- Hanya satu token argumen yang diuraikan - parser mengabaikan karakter setelah token argumen pertama.
- Perintah REM mungkin muncul dalam output fase 3, tetapi perintah itu tidak pernah dieksekusi, dan teks argumen asli digaungkan - lolos dari caret tidak dihapus, kecuali ...
- Jika hanya ada satu token argumen yang berakhir dengan unescaped
^
yang mengakhiri baris, maka token argumen dibuang, dan baris berikutnya diuraikan dan ditambahkan ke REM. Ini berulang sampai ada lebih dari satu token, atau karakter terakhir tidak ^
.
- Jika token perintah dimulai dengan
:
, dan ini adalah babak pertama fase 2 (bukan restart karena CALL di fase 6) maka
- Token biasanya diperlakukan sebagai Label Tidak Eksekusi .
- Sisa dari garis-parsing, namun
)
, <
, >
, &
dan |
tidak lagi memiliki arti khusus. Seluruh sisa baris dianggap sebagai bagian dari label "perintah".
- The
^
terus menjadi istimewa, yang berarti bahwa garis kelanjutan dapat digunakan untuk menambahkan baris berikutnya untuk label.
- Sebuah Label unexecuted dalam blok kurung akan menghasilkan kesalahan sintaks yang fatal kecuali segera diikuti dengan perintah atau dieksekusi Label pada baris berikutnya.
(
tidak lagi memiliki arti khusus untuk perintah pertama yang mengikuti Label Tidak Eksekusi .
- Perintah dibatalkan setelah penguraian label selesai. Fase berikutnya tidak terjadi untuk label
- Ada tiga pengecualian yang dapat menyebabkan label yang ditemukan di fase 2 diperlakukan sebagai Label yang Dieksekusi yang terus diurai melalui fase 7.
- Ada pengalihan yang mendahului label token, dan ada
|
pipa atau &
, &&
atau ||
perintah Rangkaian pada baris.
- Ada pengalihan yang mendahului token label, dan perintah berada di dalam blok yang di-kurung.
- Token label adalah perintah pertama pada baris di dalam blok yang di-kurung, dan baris di atas berakhir dengan Label yang Tidak Dieksekusi .
- Berikut ini terjadi ketika Label Eksekusi ditemukan dalam fase 2
- Label, argumennya, dan pengalihannya semua dikecualikan dari output gema dalam fase 3
- Setiap perintah berikutnya yang digabungkan pada baris sepenuhnya diurai dan dieksekusi.
- Untuk informasi lebih lanjut tentang Label Dieksekusi vs Label tidak dijalankan , lihat https://www.dostips.com/forum/viewtopic.php?f=3&t=3803&p=55405#p55405
Fase 3) Gema perintah terurai hanya jika blok perintah tidak dimulai @
, dan ECHO AKTIF pada awal langkah sebelumnya.
Fase 4) UNTUK %X
ekspansi variabel: Hanya jika perintah FOR aktif dan perintah setelah DO sedang diproses.
- Pada titik ini, fase 1 pemrosesan batch akan telah mengubah variabel FOR seperti
%%X
menjadi %X
. Baris perintah memiliki aturan ekspansi persen berbeda untuk fase 1. Ini adalah alasan bahwa baris perintah menggunakan %X
tetapi file batch digunakan %%X
untuk variabel FOR.
- UNTUK nama variabel adalah case sensitive, tetapi
~modifiers
tidak case case.
~modifiers
didahulukan dari nama variabel. Jika karakter berikut ~
adalah pengubah dan nama variabel UNTUK yang valid, dan ada karakter berikutnya yang merupakan nama variabel UNTUK yang aktif, maka karakter tersebut diartikan sebagai pengubah.
- UNTUK nama variabel bersifat global, tetapi hanya dalam konteks klausa DO. Jika sebuah rutin PANGGILAN dari dalam klausa DO DO, maka variabel UNTUK tidak diperluas dalam rutin PANGGILAN. Tetapi jika rutin memiliki perintah FOR sendiri, maka semua variabel FOR saat ini didefinisikan dapat diakses oleh perintah DO dalam.
- UNTUK nama variabel dapat digunakan kembali dalam FOR yang bersarang. Nilai FOR bagian dalam didahulukan, tetapi begitu INNER FOR ditutup, maka nilai FOR bagian luar dipulihkan.
- Jika ECHO AKTIF pada awal fase ini, maka fase 3) diulang untuk menunjukkan perintah DO yang diuraikan setelah variabel UNTUK telah diperluas.
---- Dari titik ini dan seterusnya, setiap perintah yang diidentifikasi dalam fase 2 diproses secara terpisah.
---- Fase 5 hingga 7 diselesaikan untuk satu perintah sebelum pindah ke yang berikutnya.
Fase 5) Ekspansi Tertunda: Hanya jika ekspansi yang tertunda aktif, perintah tidak ada dalam tanda kurung di kedua sisi pipa , dan perintah itu bukan skrip batch "telanjang" (nama skrip tanpa tanda kurung, CALL, gabungan perintah, atau pipa).
- Setiap token untuk perintah diuraikan untuk ekspansi yang tertunda secara independen.
- Kebanyakan perintah mem-parsing dua atau lebih token - token perintah, token argumen, dan masing-masing token tujuan pengalihan.
- Perintah FOR mem-parsing token klausa IN saja.
- Perintah IF mem-parsing nilai perbandingan hanya - satu atau dua, tergantung pada operator perbandingan.
- Untuk setiap token yang diuraikan, periksa dulu apakah itu berisi
!
. Jika tidak, maka token tidak diuraikan - penting untuk ^
karakter. Jika tokennya berisi !
, maka pindai setiap karakter dari kiri ke kanan:
- Jika itu adalah tanda sisipan (
^
) karakter selanjutnya tidak memiliki arti khusus, tanda sisipan itu sendiri dihapus
- Jika itu adalah tanda seru, cari tanda seru berikutnya (tanda sisipan tidak diamati lagi), perluas nilai variabel.
- Pembukaan berturut-turut
!
diciutkan menjadi satu!
- Sisa yang tidak berpasangan
!
dihapus
- Memperluas vars pada tahap ini adalah "aman", karena karakter khusus tidak terdeteksi lagi (genap
<CR>
atau <LF>
)
- Untuk penjelasan yang lebih lengkap, bacalah bagian kedua dari utas yang sama dari dbenham
- Exclamation Point Phase
Fase 5.3) Pemrosesan pipa: Hanya jika perintah ada di kedua sisi pipa
Setiap sisi pipa diproses secara independen dan tidak sinkron.
- Jika perintah internal ke cmd.exe, atau itu adalah file batch, atau jika itu adalah blok perintah yang disisipkan, maka dieksekusi di thread cmd.exe baru melalui
%comspec% /S /D /c" commandBlock"
, jadi blok perintah mendapat fase restart, tapi kali ini dalam mode baris perintah.
- Jika blok perintah di-kurung, maka semua
<LF>
dengan perintah sebelum dan sesudah dikonversi ke <space>&
. Lainnya <LF>
dilucuti.
- Ini adalah akhir dari pemrosesan untuk perintah pipa.
- Lihat Mengapa ekspansi tertunda gagal ketika di dalam blok kode pipa? untuk lebih lanjut tentang penguraian dan pemrosesan pipa
Fase 5.5) Eksekusi Pengalihan: Setiap pengalihan yang ditemukan dalam fase 2 sekarang dieksekusi.
Fase 6) Pemrosesan CALL / Penggandaan Caret: Hanya jika token perintahnya adalah CALL, atau jika teks sebelum pembatas token standar yang pertama kali muncul adalah CALL. Jika CALL diuraikan dari token perintah yang lebih besar, maka bagian yang tidak digunakan akan ditambahkan ke token argumen sebelum melanjutkan.
- Pindai token argumen untuk tanda kutip
/?
. Jika ditemukan di mana saja di dalam token, batalkan fase 6 dan lanjutkan ke Tahap 7, di mana BANTUAN untuk CALL akan dicetak.
- Hapus yang pertama
CALL
, sehingga beberapa PANGGILAN dapat ditumpuk
- Gandakan semua karat
- Mulai ulang fase 1, 1.5, dan 2, tetapi jangan melanjutkan ke fase 3
- Setiap dua kali lipat karat dikurangi kembali menjadi satu karat sepanjang mereka tidak dikutip. Namun sayangnya, kutipan caret tetap berlipat ganda.
- Fase 1 sedikit berubah
- Kesalahan ekspansi dalam langkah 1.2 atau 1.3 batalkan CALL, tetapi kesalahan itu tidak fatal - pemrosesan batch berlanjut.
- Tugas fase 2 sedikit diubah
- Setiap pengarahan ulang tanpa tanda kutip yang baru muncul dan tidak terdeteksi yang tidak terdeteksi pada putaran pertama fase 2 terdeteksi, tetapi dihapus (termasuk nama file) tanpa benar-benar melakukan pengalihan tersebut.
- Setiap tanda tanda kutip tanpa tanda kutip yang baru muncul dan tidak terhapus di akhir baris dihapus tanpa melakukan kelanjutan garis
- PANGGILAN dibatalkan tanpa kesalahan jika salah satu dari yang berikut terdeteksi
- Baru muncul tanpa kutip, tidak terhapus
&
atau|
- Token perintah yang dihasilkan dimulai dengan tanda kutip, unescaped
(
- Token pertama setelah CALL yang dihapus dimulai dengan
@
- Jika perintah yang dihasilkan adalah IF atau FOR yang tampaknya valid, maka eksekusi selanjutnya akan gagal dengan kesalahan yang menyatakan bahwa
IF
atau FOR
tidak diakui sebagai perintah internal atau eksternal.
- Tentu saja PANGGILAN tidak dibatalkan dalam putaran 2 fase 2 ini jika token perintah yang dihasilkan adalah label yang dimulai dengan
:
.
- Jika token perintah yang dihasilkan adalah PANGGILAN, maka restart Fase 6 (ulangi sampai tidak ada lagi PANGGILAN)
- Jika token perintah yang dihasilkan adalah skrip batch atau label:, maka eksekusi CALL sepenuhnya ditangani oleh sisa Fase 6.
- Dorong posisi file skrip batch saat ini di tumpukan panggilan sehingga eksekusi dapat dilanjutkan dari posisi yang benar ketika CALL selesai.
- Siapkan token argumen% 0,% 1,% 2, ...% N dan% * untuk CALL, menggunakan semua token yang dihasilkan
- Jika token perintah adalah label yang dimulai dengan
:
, maka
- Mulai ulang Fase 5. Hal ini dapat memengaruhi apa: label ditelepon. Tetapi karena% 0 dll. Token sudah diatur, itu tidak akan mengubah argumen yang diteruskan ke rutin yang ditelepon.
- Jalankan label GOTO untuk memposisikan penunjuk file di awal subrutin (abaikan token lain yang mungkin mengikuti: label) Lihat Tahap 7 untuk aturan tentang cara kerja GOTO.
- Lain kontrol transfer ke skrip batch yang ditentukan.
- Eksekusi dari CALLed: label atau script berlanjut sampai EXIT / B atau end-of-file tercapai, pada saat mana stack CALL muncul dan eksekusi kembali dari posisi file yang disimpan.
Fase 7 tidak dijalankan untuk skrip yang ditelepon atau: label.
- Jika tidak, hasil fase 6 akan masuk ke fase 7 untuk dieksekusi.
Tahap 7) Jalankan: Perintah dijalankan
- 7.1 - Jalankan perintah internal - Jika token perintah dikutip, lewati langkah ini. Kalau tidak, cobalah untuk menguraikan perintah internal dan mengeksekusi.
- Tes berikut dilakukan untuk menentukan apakah token perintah yang tidak dikutip mewakili perintah internal:
- Jika token perintah sama persis dengan perintah internal, maka jalankan.
- Lain memecahkan token perintah sebelum kejadian pertama
+
/
[
]
<space>
<tab>
,
;
atau =
Jika teks sebelumnya adalah perintah internal, maka ingat perintah itu
- Jika dalam mode baris perintah, atau jika perintah berasal dari blok yang dikurung, JIKA blok perintah benar atau salah, blok perintah FOR DO, atau terlibat dengan perintah gabungan, kemudian jalankan perintah internal
- Lain (harus berupa perintah yang berdiri sendiri dalam mode batch) memindai folder saat ini dan PATH untuk file .COM, .EXE, .BAT, atau .CMD yang nama dasarnya cocok dengan token perintah asli
- Jika file yang cocok pertama adalah .BAT atau .CMD, maka goto 7.3.exec dan jalankan skrip itu
- Lain (pertandingan tidak ditemukan atau pertandingan pertama adalah .EXE atau .COM) jalankan perintah internal yang diingat
- Jika tidak, pecahkan token perintah sebelum kemunculan pertama
.
\
atau :
Jika teks sebelumnya bukan perintah internal, maka pergi ke 7.2.
Jika tidak, teks sebelumnya mungkin merupakan perintah internal. Ingat perintah ini.
- Break token perintah sebelum kejadian pertama
+
/
[
]
<space>
<tab>
,
;
atau =
Jika teks sebelumnya adalah path ke file yang sudah ada, maka goto 7.2
Else melaksanakan perintah internal yang diingat.
- Jika perintah internal diuraikan dari token perintah yang lebih besar, maka bagian token perintah yang tidak digunakan termasuk dalam daftar argumen
- Hanya karena token perintah diuraikan sebagai perintah internal tidak berarti itu akan berhasil dijalankan. Setiap perintah internal memiliki aturan sendiri tentang bagaimana argumen dan opsi diuraikan, dan sintaks apa yang diizinkan.
- Semua perintah internal akan mencetak bantuan alih-alih menjalankan fungsinya jika
/?
terdeteksi. Kebanyakan mengenali /?
jika itu muncul di mana saja dalam argumen. Tetapi beberapa perintah seperti ECHO dan SET hanya mencetak bantuan jika token argumen pertama dimulai /?
.
- SET memiliki beberapa semantik yang menarik:
- Jika perintah SET memiliki kutipan sebelum nama variabel dan ekstensi diaktifkan
set "name=content" ignored
-> value = content
maka teks antara tanda sama dengan pertama dan kutipan terakhir digunakan sebagai konten (sama dengan kutipan pertama dan terakhir dikecualikan). Teks setelah kutipan terakhir diabaikan. Jika tidak ada kutipan setelah tanda sama dengan, maka sisa baris digunakan sebagai konten.
- Jika perintah SET tidak memiliki kutipan di depan nama
set name="content" not ignored
-> nilai = "content" not ignored
maka seluruh sisa baris setelah sama digunakan sebagai konten, termasuk setiap dan semua kutipan yang mungkin ada.
- Perbandingan IF dievaluasi, dan tergantung pada apakah kondisinya benar atau salah, blok perintah dependen yang sudah diuraikan diproses, dimulai dengan fase 5.
- Klausa IN dari perintah FOR diulang dengan tepat.
- Jika ini adalah FOR / F yang mengulang output dari blok perintah, maka:
- Klausa IN dieksekusi dalam proses cmd.exe baru melalui CMD / C.
- Blok perintah harus melalui seluruh proses parsing untuk kedua kalinya, tetapi kali ini dalam konteks baris perintah
- ECHO akan mulai ON, dan ekspansi yang tertunda biasanya akan mulai dinonaktifkan (tergantung pada pengaturan registri)
- Semua perubahan lingkungan yang dibuat oleh blok perintah klausa IN akan hilang setelah proses cmd.exe anak berakhir
- Untuk setiap iterasi:
- Nilai variabel FOR didefinisikan
- Blok perintah DO yang sudah diuraikan kemudian diproses, dimulai dengan fase 4.
- GOTO menggunakan logika berikut untuk menemukan: label
- Label diuraikan dari token argumen pertama
- Script dipindai untuk kemunculan label berikutnya
- Pemindaian dimulai dari posisi file saat ini
- Jika akhir file tercapai, maka pemindaian akan kembali ke awal file dan berlanjut ke titik awal yang asli.
- Pemindaian berhenti pada kemunculan pertama label yang ditemukannya, dan penunjuk file diatur ke garis segera setelah label. Eksekusi naskah dilanjutkan dari titik itu. Perhatikan bahwa GOTO sejati yang berhasil akan segera membatalkan blok kode yang diuraikan, termasuk loop FOR.
- Jika label tidak ditemukan, atau token label hilang, maka GOTO gagal, pesan kesalahan dicetak, dan tumpukan panggilan muncul. Ini berfungsi secara efektif sebagai EXIT / B, kecuali perintah yang sudah diuraikan dalam blok perintah saat ini yang mengikuti GOTO masih dieksekusi, tetapi dalam konteks Penelpon (konteks yang ada setelah EXIT / B)
- Lihat https://www.dostips.com/forum/viewtopic.php?f=3&t=3803 untuk deskripsi yang lebih tepat tentang aturan yang digunakan untuk mengurai label.
- RENAME dan COPY menerima wildcard untuk jalur sumber dan target. Tetapi Microsoft melakukan pekerjaan yang mengerikan dengan mendokumentasikan cara kerja wildcard, terutama untuk jalur target. Serangkaian aturan wildcard yang berguna dapat ditemukan di Bagaimana perintah Windows RENAME mengartikan wildcard?
- 7.2 - Jalankan perubahan volume - Lain-lain jika token perintah tidak dimulai dengan kutipan, panjangnya tepat dua karakter, dan karakter ke-2 adalah titik dua, kemudian ubah volume
- Semua token argumen diabaikan
- Jika volume yang ditentukan oleh karakter pertama tidak dapat ditemukan, maka batalkan dengan kesalahan
- Token perintah
::
akan selalu menghasilkan kesalahan kecuali SUBST digunakan untuk menentukan volume untuk. ::
Jika SUBST digunakan untuk menentukan volume ::
, maka volume akan diubah, itu tidak akan diperlakukan sebagai label.
- 7.3 - Menjalankan perintah eksternal - Lain-lain mencoba memperlakukan perintah sebagai perintah eksternal.
- Jika dalam mode baris perintah dan perintah tidak dikutip dan tidak dimulai dengan spesifikasi volume, white-space,
,
, ;
, =
atau +
kemudian istirahat perintah tanda pada kejadian pertama <space>
,
;
atau =
dan tambahkan sisa argumen token (s).
- Jika karakter 2 dari token perintah adalah titik dua, maka verifikasi volume yang ditentukan oleh karakter 1 dapat ditemukan.
Jika volume tidak dapat ditemukan, maka batalkan dengan kesalahan.
- Jika dalam mode batch dan token perintah dimulai dengan
:
, maka goto 7.4
Perhatikan bahwa jika token label dimulai dengan ::
, maka ini tidak akan tercapai karena langkah sebelumnya akan dibatalkan dengan kesalahan kecuali SUBST digunakan untuk menentukan volume untuk ::
.
- Identifikasi perintah eksternal untuk dieksekusi.
- Ini adalah proses kompleks yang mungkin melibatkan volume saat ini, direktori saat ini, variabel PATH, variabel PATHEXT, dan atau asosiasi file.
- Jika perintah eksternal yang valid tidak dapat diidentifikasi, maka batalkan dengan kesalahan.
- Jika dalam mode baris perintah dan token perintah dimulai dengan
:
, maka goto 7.4
Perhatikan bahwa ini jarang tercapai karena langkah sebelumnya akan dibatalkan dengan kesalahan kecuali jika token perintah dimulai dengan ::
, dan SUBST digunakan untuk menentukan volume untuk::
, dan Seluruh token perintah adalah jalur yang valid ke perintah eksternal.
- 7.3.exec - Jalankan perintah eksternal.
- 7.4 - Abaikan label - Abaikan perintah dan semua argumennya jika token perintah dimulai
:
.
Aturan dalam 7.2 dan 7.3 dapat mencegah label mencapai titik ini.
Parser Baris Perintah:
Bekerja seperti BatchLine-Parser, kecuali:
Fase 1) Ekspansi Persen:
- Tidak
%*
, %1
dll. Perluasan argumen
- Jika var tidak terdefinisi, maka
%var%
dibiarkan tidak berubah.
- Tidak ada penanganan khusus
%%
. Jika var = konten, maka %%var%%
perluas %content%
.
Fase 3) Gema perintah yang diuraikan
- Ini tidak dilakukan setelah fase 2. Ini hanya dilakukan setelah fase 4 untuk blok perintah FOR DO.
Fase 5) Ekspansi Tertunda: hanya jika Ekspansi Tertunda diaktifkan
- Jika var tidak terdefinisi, maka
!var!
dibiarkan tidak berubah.
Fase 7) Jalankan Perintah
- Upaya untuk CALL atau GOTO a: label mengakibatkan kesalahan.
- Seperti yang sudah didokumentasikan dalam fase 7, label yang dieksekusi dapat mengakibatkan kesalahan di bawah skenario yang berbeda.
- Label yang dijalankan batch hanya dapat menyebabkan kesalahan jika dimulai dengan
::
- Label baris perintah yang dijalankan hampir selalu menghasilkan kesalahan
Parsing dari nilai integer
Ada banyak konteks berbeda di mana cmd.exe mem-parsing nilai integer dari string, dan aturannya tidak konsisten:
SET /A
IF
%var:~n,m%
(ekspansi substring variabel)
FOR /F "TOKENS=n"
FOR /F "SKIP=n"
FOR /L %%A in (n1 n2 n3)
EXIT [/B] n
Detail untuk aturan ini dapat ditemukan di Aturan untuk bagaimana CMD.EXE mem-parsing angka
Bagi siapa pun yang ingin meningkatkan aturan parsing cmd.exe, ada topik diskusi di forum DosTips di mana masalah dapat dilaporkan dan saran dibuat.
Semoga membantu
Jan Erik (jeb) - Penulis asli dan penemu fase
Dave Benham (dbenham) - Banyak konten tambahan dan pengeditan