Apa saja fitur dan batasan tidak terdokumentasi dari perintah Windows FINDSTR?

188

Perintah Windows FINDSTR didokumentasikan dengan mengerikan. Ada bantuan baris perintah yang sangat dasar tersedia melalui FINDSTR /?, atau HELP FINDSTR, tetapi sangat tidak memadai. Ada sedikit dokumentasi online lagi di https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/findstr .

Ada banyak fitur dan batasan FINDSTR yang bahkan tidak diisyaratkan dalam dokumentasi. Mereka juga tidak dapat diantisipasi tanpa pengetahuan sebelumnya dan / atau eksperimen yang cermat.

Jadi pertanyaannya adalah - Apa saja fitur dan batasan FINDSTR yang tidak berdokumen?

Tujuan dari pertanyaan ini adalah untuk menyediakan repositori lengkap dari banyak fitur yang tidak terdokumentasi sehingga:

A) Pengembang dapat mengambil keuntungan penuh dari fitur yang ada.

B) Pengembang tidak membuang-buang waktu mereka bertanya-tanya mengapa sesuatu tidak berfungsi padahal seharusnya demikian.

Pastikan Anda mengetahui dokumentasi yang ada sebelum merespons. Jika informasi tersebut dicakup oleh BANTUAN, maka itu bukan milik di sini.

Ini juga bukan tempat untuk menunjukkan kegunaan FINDSTR yang menarik. Jika orang yang logis dapat mengantisipasi perilaku penggunaan FINDSTR tertentu berdasarkan pada dokumentasi, maka itu tidak termasuk di sini.

Sejalan dengan itu, jika orang yang logis dapat mengantisipasi perilaku penggunaan tertentu berdasarkan informasi yang terkandung dalam jawaban yang ada, maka sekali lagi, itu tidak termasuk di sini.

dbenham
sumber
15
Atau, alternatif, Anda bisa parit jelek utilitas MS tidak berdokumen sama sekali dan install / gunakan grepyang ini sangat dipahami dengan baik dan didokumentasikan :-) Lihat stackoverflow.com/questions/2635740/... misalnya.
paxdiablo
17
Dengan segala cara, jika Anda berada dalam posisi untuk menggunakan sesuatu selain FINDSTR, maka itu sangat disarankan. Tetapi beberapa orang berada di lingkungan di mana utilitas pihak ke-3 dilarang.
dbenham
4
Jangan tersinggung. Saya serius mempertimbangkan untuk menempatkan disclaimer FINDSTR saya sendiri yang mirip dengan komentar Anda! :)
dbenham
41
Saya terkejut dan kecewa seseorang akan menemukan pertanyaan ini "Tidak Konstruktif" dan memilih untuk menutup. Banyak pemikiran masuk ke pertanyaan khusus untuk menghindari "opini, debat, argumen, polling, atau diskusi panjang". Pertanyaan telah diposting selama 3,5 bulan, dan tidak ada negatif yang dikutip telah terjadi. Jawaban berpasangan diisi dengan fakta-fakta, dan diperlukan berjam-jam penelitian dan eksperimen yang melelahkan.
dbenham
6
Beberapa pembaca mungkin tertarik dengan konteks historis dari perintah findstr: blogs.msdn.com/b/oldnewthing/archive/2012/11/28/10372436.aspx
Harry Johnston

Jawaban:

279

Pendahuluan
Banyak informasi dalam jawaban ini telah dikumpulkan berdasarkan percobaan yang dijalankan pada mesin Vista. Kecuali secara eksplisit dinyatakan sebaliknya, saya belum mengkonfirmasi apakah informasi tersebut berlaku untuk versi Windows lainnya.

Output FINDSTR
Dokumentasi tidak pernah mau repot untuk menjelaskan output FINDSTR. Ini menyinggung fakta bahwa garis yang cocok dicetak, tetapi tidak lebih.

Format output garis yang cocok adalah sebagai berikut:

nama file: lineNumber: lineOffset: teks

dimana

nama file: = Nama file yang berisi baris yang cocok. Nama file tidak dicetak jika permintaan secara eksplisit untuk satu file, atau jika mencari input yang dipipihkan atau input yang dialihkan. Saat dicetak, nama file akan selalu menyertakan informasi jalur yang disediakan. Informasi jalur tambahan akan ditambahkan jika /Sopsi digunakan. Jalur yang dicetak selalu relatif terhadap jalur yang disediakan, atau relatif terhadap direktori saat ini jika tidak ada yang disediakan.

Catatan - Awalan nama file dapat dihindari saat mencari beberapa file dengan menggunakan wildcard < dan non-standar> . Aturan pasti untuk cara kerja wildcard ini dapat ditemukan di sini . Terakhir, Anda dapat melihat contoh ini tentang cara kerja wildcard non-standar dengan FINDSTR .

lineNumber: = Nomor baris dari garis yang cocok diwakili sebagai nilai desimal dengan 1 mewakili baris pertama dari input. Hanya dicetak jika/Nopsi ditentukan.

lineOffset: = Offset byte desimal dari awal baris yang cocok, dengan 0 mewakili karakter pertama dari baris pertama. Hanya dicetak jika/Oopsi ditentukan. Ini bukan offset dari pertandingan di dalam garis. Ini adalah jumlah byte dari awal file ke awal baris.

text = Representasi biner dari baris yang cocok, termasuk <CR> dan / atau <LF>. Tidak ada yang tersisa dari output biner, sehingga contoh ini yang cocok dengan semua baris akan menghasilkan salinan biner yang tepat dari file asli.

FINDSTR "^" FILE >FILE_COPY

Opsi / A mengatur warna fileName :, lineNumber :, dan lineOffset: output saja. Teks dari baris yang cocok selalu ditampilkan dengan warna konsol saat ini. Opsi / A hanya berpengaruh ketika output ditampilkan langsung ke konsol. Opsi / A tidak berpengaruh jika output diarahkan ke file atau disalurkan. Lihat hasil edit 2018-08-18 dalam jawaban Aacini untuk deskripsi perilaku kereta ketika output diarahkan ke CON.

Sebagian besar karakter kontrol dan banyak karakter ASCII yang diperluas ditampilkan sebagai titik pada XP
FINDSTR pada XP menampilkan sebagian besar karakter kontrol yang tidak dapat dicetak dari garis yang cocok sebagai titik (titik) pada layar. Karakter kontrol berikut adalah pengecualian; mereka ditampilkan sebagai diri mereka sendiri: Tab 0x09, LineFeed 0x0A, Tab Vertikal 0x0B, Umpan Form 0x0C, Pengembalian Carriage 0x0D.

XP FINDSTR juga mengubah sejumlah karakter ASCII yang diperluas menjadi titik juga. Karakter ASCII yang diperluas yang ditampilkan sebagai titik-titik pada XP sama dengan yang diubah ketika diberikan pada baris perintah. Lihat bagian "Batas karakter untuk parameter baris perintah - Transformasi ASCII yang diperluas" , nanti dalam posting ini

Karakter kontrol dan ASCII yang diperluas tidak dikonversi ke titik-titik pada XP jika outputnya disalurkan, dialihkan ke file, atau dalam klausa FOR IN ().

Vista dan Windows 7 selalu menampilkan semua karakter sebagai diri mereka sendiri, tidak pernah sebagai titik.

Kembalikan Kode (ERRORLEVEL)

  • 0 (sukses)
    • Kecocokan ditemukan di setidaknya satu baris setidaknya satu file.
  • 1 (gagal)
    • Tidak ada kecocokan yang ditemukan di baris file apa pun.
    • Warna tidak valid ditentukan oleh /A:xxopsi
  • 2 (kesalahan)
    • Opsi yang tidak kompatibel /Ldan /Rkeduanya ditentukan
    • Hilang argumen setelah /A:, /F:, /C:, /D:, atau/G:
    • File ditentukan oleh /F:fileatau /G:filetidak ditemukan
  • 255 (kesalahan)

Sumber data untuk pencarian (Diperbarui berdasarkan tes dengan Windows 7)
Findstr dapat mencari data hanya dari salah satu sumber berikut:

  • nama file ditentukan sebagai argumen dan / atau menggunakan /F:fileopsi.

  • stdin melalui pengalihan findstr "searchString" <file

  • aliran data dari pipa type file | findstr "searchString"

Argumen / opsi diutamakan alih redirection, yang lebih diutamakan daripada data pipa.

Argumen nama file dan /F:filedapat digabungkan. Beberapa argumen nama file dapat digunakan. Jika beberapa /F:fileopsi ditentukan, maka hanya yang terakhir digunakan. Kartu liar diizinkan dalam argumen nama file, tetapi tidak dalam file yang ditunjuk oleh /F:file.

Sumber string pencarian (Updated berdasarkan tes dengan Windows 7)
The /G:filedan /C:stringpilihan dapat dikombinasikan. Beberapa /C:stringopsi dapat ditentukan. Jika beberapa /G:fileopsi ditentukan, maka hanya yang terakhir digunakan. Jika salah satu /G:fileatau /C:stringdigunakan, maka semua argumen non-opsi diasumsikan sebagai file untuk dicari. Jika tidak satu pun /G:filetidak /C:stringdigunakan, maka argumen non-opsi pertama diperlakukan sebagai daftar istilah pencarian yang dibatasi ruang.

Nama file tidak boleh dikutip dalam file saat menggunakan /F:FILEopsi.
Nama file dapat berisi spasi dan karakter khusus lainnya. Sebagian besar perintah mengharuskan nama file tersebut dikutip. Tetapi /F:files.txtopsi FINDSTR mensyaratkan bahwa nama file di dalam files.txt TIDAK boleh dikutip. File tidak akan ditemukan jika namanya dikutip.

BUG - Nama file 8,3 pendek dapat memecahkan /Ddan /Sopsi
Seperti dengan semua perintah Windows, FINDSTR akan berusaha untuk mencocokkan nama panjang dan nama 8.3 pendek ketika mencari file untuk mencari. Asumsikan folder saat ini berisi file-file tidak kosong berikut:

b1.txt
b.txt2
c.txt

Perintah berikut akan berhasil menemukan semua 3 file:

findstr /m "^" *.txt

b.txt2cocok karena nama pendek yang sesuai B9F64~1.TXTcocok. Ini konsisten dengan perilaku semua perintah Windows lainnya.

Tetapi bug dengan opsi /Ddan /Smenyebabkan perintah berikut hanya menemukanb1.txt

findstr /m /d:. "^" *.txt
findstr /m /s "^" *.txt

Bug mencegah b.txt2ditemukan, serta semua nama file yang diurutkan setelah b.txt2dalam direktori yang sama. File tambahan yang mengurutkan sebelumnya, seperti a.txt, ditemukan. File tambahan yang mengurutkan kemudian, seperti d.txt, dilewatkan begitu bug telah dipicu.

Setiap direktori yang dicari diperlakukan secara independen. Misalnya, /Sopsi tersebut akan berhasil mulai mencari di folder anak setelah gagal menemukan file di induknya, tetapi begitu bug tersebut menyebabkan nama file pendek terlewatkan pada anak, maka semua file berikutnya dalam folder anak itu juga akan terlewatkan .

Perintah ini berfungsi bebas bug jika nama file yang sama dibuat pada mesin yang menonaktifkan pembuatan nama NTFS 8.3. Tentu saja b.txt2tidak akan ditemukan, tetapi c.txtakan ditemukan dengan benar.

Tidak semua nama pendek memicu bug. Semua contoh perilaku disadap yang saya lihat melibatkan ekstensi yang lebih panjang dari 3 karakter dengan nama pendek 8.3 yang dimulai sama dengan nama normal yang tidak memerlukan nama 8.3.

Bug telah dikonfirmasi pada XP, Vista, dan Windows 7.

Karakter non-cetak dan /Ppilihan
The /Popsi menyebabkan FINDSTR untuk melewati file yang berisi salah satu kode desimal byte berikut:
0-7, 14-25, 27-31.

Dengan kata lain, /Popsi ini hanya akan melewatkan file yang berisi karakter kontrol yang tidak dapat dicetak. Karakter kontrol adalah kode yang kurang dari atau sama dengan 31 (0x1F). FINDSTR memperlakukan karakter kontrol berikut ini sebagai dapat dicetak:

 8  0x08  backspace
 9  0x09  horizontal tab
10  0x0A  line feed
11  0x0B  vertical tab
12  0x0C  form feed
13  0x0D  carriage return
26  0x1A  substitute (end of text)

Semua karakter kontrol lainnya diperlakukan sebagai tidak dapat dicetak, yang keberadaannya menyebabkan /Popsi untuk melewatkan file.

Input yang Dipipakan dan Diarahkan ulang mungkin telah <CR><LF>ditambahkan.
Jika input tersebut disalurkan ke dalam dan karakter terakhir dari aliran tidak <LF>, maka FINDSTR akan secara otomatis menambahkan <CR><LF>ke input. Ini telah dikonfirmasi pada XP, Vista dan Windows 7. (Dulu saya berpikir bahwa pipa Windows bertanggung jawab untuk memodifikasi input, tetapi sejak itu saya menemukan bahwa FINDSTR sebenarnya melakukan modifikasi.)

Hal yang sama berlaku untuk input yang dialihkan ke Vista. Jika karakter terakhir dari file yang digunakan sebagai input redirected bukan <LF>, maka FINDSTR akan secara otomatis menambahkan <CR><LF>ke input. Namun, XP dan Windows 7 tidak mengubah input yang dialihkan.

FINDSTR hang pada XP dan Windows 7 jika input yang dialihkan tidak berakhir dengan<LF>
Ini adalah "fitur" yang jahat di XP dan Windows 7. Jika karakter terakhir dari file yang digunakan sebagai input yang dialihkan tidak berakhir <LF>, maka FINDSTR akan menggantung tanpa batas setelah itu mencapai akhir file yang diarahkan.

Baris terakhir dari data Piped dapat diabaikan jika terdiri dari satu karakter.
Jika input disalurkan dan baris terakhir terdiri dari satu karakter yang tidak diikuti <LF>, maka FINDSTR sepenuhnya mengabaikan baris terakhir.

Contoh - Perintah pertama dengan satu karakter dan tidak <LF>gagal untuk mencocokkan, tetapi perintah kedua dengan 2 karakter berfungsi dengan baik, seperti halnya perintah ketiga yang memiliki satu karakter dengan mengakhiri baris baru.

> set /p "=x" <nul | findstr "^"

> set /p "=xx" <nul | findstr "^"
xx

> echo x| findstr "^"
x

Dilaporkan oleh pengguna DosTips, Sponge Belly di bug findstr baru . Dikonfirmasi pada XP, Windows 7 dan Windows 8. Belum pernah mendengar tentang Vista. (Saya tidak lagi memiliki Vista untuk diuji).

Sintaksis
Opsi Opsi dapat diawali dengan salah satu /atau - Opsi dapat disatukan setelah satu /atau -. Namun, daftar opsi gabungan dapat memuat paling banyak satu opsi multi-karakter seperti OFF atau F :, dan opsi multi-karakter harus menjadi opsi terakhir dalam daftar.

Berikut ini adalah semua cara yang setara untuk mengekspresikan pencarian regex case tidak sensitif untuk setiap baris yang berisi "halo" dan "selamat tinggal" dalam urutan apa pun

  • /i /r /c:"hello.*goodbye" /c:"goodbye.*hello"

  • -i -r -c:"hello.*goodbye" /c:"goodbye.*hello"

  • /irc:"hello.*goodbye" /c:"goodbye.*hello"

Batas panjang String Pencarian
Pada Vista, panjang maksimum yang diizinkan untuk string pencarian tunggal adalah 511 byte. Jika ada string pencarian melebihi 511 maka hasilnya adalah FINDSTR: Search string too long.kesalahan dengan ERRORLEVEL 2.

Saat melakukan pencarian ekspresi reguler, panjang string pencarian maksimum adalah 254. Ekspresi reguler dengan panjang antara 255 dan 511 akan menghasilkan FINDSTR: Out of memorykesalahan dengan ERRORLEVEL 2. Panjang ekspresi reguler> 511 menghasilkan FINDSTR: Search string too long.kesalahan.

Pada Windows XP panjang string pencarian tampaknya lebih pendek. Galat Findstr: "Cari string terlalu panjang": Bagaimana cara mengekstrak dan mencocokkan substring dalam loop "for"? Batas XP adalah 127 byte untuk pencarian literal dan regex.

Batas Panjang Baris
File ditentukan sebagai argumen baris perintah atau melalui opsi / F: FILE tidak memiliki batas panjang garis yang diketahui. Pencarian berhasil dijalankan terhadap file 128MB yang tidak mengandung satu <LF>.

Data pipa dan input Redirected terbatas pada 8191 byte per baris. Batas ini adalah "fitur" dari FINDSTR. Itu tidak melekat pada pipa atau pengalihan. FINDSTR menggunakan stdin atau input yang dialihkan tidak akan pernah cocok dengan garis apa pun yang> = 8k byte. Lines> = 8k menghasilkan pesan kesalahan ke stderr, tetapi ERRORLEVEL masih 0 jika string pencarian ditemukan di setidaknya satu baris dari setidaknya satu file.

Jenis pencarian default: Ekspresi literal vs Reguler
/C:"string" - Standarnya adalah / L literal. Secara eksplisit menggabungkan opsi / L dengan / C: "string" tentu saja bekerja tetapi berlebihan.

"string argument"- Default tergantung pada konten string pencarian pertama. (Ingat bahwa <spasi> digunakan untuk membatasi string pencarian.) Jika string pencarian pertama adalah ekspresi reguler yang valid yang mengandung setidaknya satu meta-karakter yang tidak diloloskan, maka semua string pencarian diperlakukan sebagai ekspresi reguler. Kalau tidak, semua string pencarian diperlakukan sebagai literal. Misalnya, "51.4 200"akan diperlakukan sebagai dua ekspresi reguler karena string pertama berisi titik yang tidak diloloskan, sedangkan "200 51.4"akan diperlakukan sebagai dua literal karena string pertama tidak mengandung meta-karakter.

/G:file- Default tergantung pada konten dari baris non-kosong pertama dalam file. Jika string pencarian pertama adalah ekspresi reguler yang valid yang berisi setidaknya satu meta-karakter yang tidak diloloskan, maka semua string pencarian diperlakukan sebagai ekspresi reguler. Kalau tidak, semua string pencarian diperlakukan sebagai literal.

Rekomendasi - Selalu tentukan secara eksplisit /Lopsi literal atau /Ropsi ekspresi reguler saat menggunakan "string argument"atau /G:file.

BUG - Menentukan beberapa string pencarian literal dapat memberikan hasil yang tidak dapat diandalkan

Contoh FINDSTR sederhana berikut gagal menemukan kecocokan, meskipun seharusnya.

echo ffffaaa|findstr /l "ffffaaa faffaffddd"

Bug ini telah dikonfirmasi pada Windows Server 2003, Windows XP, Vista, dan Windows 7.

Berdasarkan percobaan, FINDSTR mungkin gagal jika semua kondisi berikut dipenuhi:

  • Pencarian menggunakan beberapa string pencarian literal
  • String pencarian memiliki panjang yang berbeda
  • String pencarian pendek memiliki sejumlah tumpang tindih dengan string pencarian yang lebih panjang
  • Pencarian sensitif huruf besar (tidak ada /Iopsi)

Dalam setiap kegagalan yang saya lihat, selalu merupakan salah satu string pencarian pendek yang gagal.

Untuk info lebih lanjut, lihat Mengapa FINDSTR ini tidak contoh dengan beberapa string pencarian literal menemukan kecocokan?

Kutipan dan backslahses dalam argumen baris perintah
Catatan - Komentar Pengguna MC ND mencerminkan aturan rumit yang sebenarnya mengerikan untuk bagian ini. Ada 3 fase penguraian yang terlibat:

  • Cmd.exe pertama mungkin memerlukan beberapa kutipan untuk diloloskan sebagai ^ "(benar-benar tidak ada hubungannya dengan FINDSTR)
  • FINDSTR Selanjutnya menggunakan parser argumen MS C / C ++ pra 2008 , yang memiliki aturan khusus untuk "dan \
  • Setelah parser argumen selesai, FINDSTR juga memperlakukan \ diikuti oleh karakter alpha-numeric sebagai literal, tetapi \ diikuti oleh karakter non-alpha-numeric sebagai karakter escape

Sisa dari bagian yang disorot ini tidak 100% benar. Ini dapat berfungsi sebagai panduan untuk banyak situasi, tetapi aturan di atas diperlukan untuk pemahaman total.

Lolos Kutipan dalam string pencarian baris perintah
Kutipan dalam string pencarian baris perintah harus diloloskan dengan seperti backslash \". Ini berlaku untuk string pencarian literal dan regex. Informasi ini telah dikonfirmasi pada XP, Vista, dan Windows 7.

Catatan: Kutipan juga mungkin perlu diloloskan untuk parser CMD.EXE, tetapi ini tidak ada hubungannya dengan FINDSTR. Misalnya, untuk mencari satu kutipan, Anda dapat menggunakan:

FINDSTR \^" file && echo found || echo not found

Meloloskan Backslash dalam string pencarian literal baris perintah.
Backslash dalam string pencarian literal biasanya dapat direpresentasikan sebagai \atau sebagai \\. Mereka biasanya setara. (Mungkin ada kasus yang tidak biasa di Vista di mana backslash harus selalu lolos, tetapi saya tidak lagi memiliki mesin Vista untuk menguji) .

Tetapi ada beberapa kasus khusus:

Saat mencari garis miring terbalik berturut-turut, semua kecuali yang terakhir harus diloloskan. Backslash terakhir secara opsional dapat dihindari.

  • \\dapat dikodekan sebagai \\\atau\\\\
  • \\\dapat dikodekan sebagai \\\\\atau\\\\\\

Mencari satu atau lebih backslash sebelum penawaran aneh. Logika akan menyarankan bahwa kutipan harus diloloskan, dan masing-masing backslash terkemuka harus diloloskan, tetapi ini tidak berhasil! Sebagai gantinya, masing-masing backslash terkemuka harus diloloskan ganda, dan kutipan diloloskan secara normal:

  • \" harus diberi kode sebagai \\\\\"
  • \\" harus diberi kode sebagai \\\\\\\\\"

Seperti disebutkan sebelumnya, satu atau lebih tanda kutip yang lolos mungkin juga memerlukan pelarian dengan ^untuk parser CMD

Info di bagian ini telah dikonfirmasi pada XP dan Windows 7.

Lolos Backslash dalam string pencarian regex baris perintah

  • Hanya Vista: Garis miring terbalik dalam regex harus berupa dua lolos \\\\, atau tunggal lolos dalam kelas karakter yang ditetapkan seperti [\\]

  • XP dan Windows 7: Backslash di regex selalu dapat direpresentasikan sebagai [\\]. Biasanya dapat direpresentasikan sebagai\\ . Tetapi ini tidak pernah berhasil jika garis miring terbalik mendahului kutipan yang lolos.

    Satu atau lebih backslash sebelum kutipan yang lolos harus berupa double escape, atau diberi kode lain [\\]

    • \"dapat dikodekan sebagai \\\\\"atau[\\]\"
    • \\"dapat dikodekan sebagai \\\\\\\\\"atau [\\][\\]\"atau\\[\\]\"

Meloloskan Kutipan dan Backslash dalam / G: FILE string pencarian literal
Standalone quotes dan backslash dalam file string pencarian literal yang ditentukan oleh / G: file tidak perlu melarikan diri, tetapi bisa juga.

" dan \" setara.

\ dan \\ setara.

Jika tujuannya adalah untuk menemukan \\, maka setidaknya backslash terkemuka harus diloloskan. Keduanya \\\dan\\\\ bekerja.

Jika maksudnya adalah untuk menemukan \ ", maka setidaknya garis miring terbalik harus diloloskan. Keduanya \\"dan\\\" berfungsi.

Lolos Kutipan dan Backslash dalam / G: FILE regex search string
Ini adalah satu kasus di mana urutan pelarian bekerja seperti yang diharapkan berdasarkan pada dokumentasi. Kutipan bukan metacharacter regex, jadi itu tidak perlu melarikan diri (tetapi bisa). Backslash adalah metacharacter regex, jadi ia harus dihilangkan.

Batas karakter untuk parameter baris perintah - Transformasi ASCII yang diperluas
Karakter nol (0x00) tidak dapat muncul di string apa pun di baris perintah. Karakter byte tunggal lainnya dapat muncul dalam string (0x01 - 0xFF). Namun, FINDSTR mengubah banyak karakter ASCII yang diperluas yang ditemukannya di dalam parameter baris perintah menjadi karakter lain. Ini memiliki dampak besar dalam dua cara:

1) Banyak karakter ASCII yang diperluas tidak akan cocok dengan dirinya sendiri jika digunakan sebagai string pencarian pada baris perintah. Batasan ini sama untuk pencarian literal dan regex. Jika string pencarian harus mengandung ASCII yang diperluas, maka the/G:FILE opsi tersebut harus digunakan sebagai gantinya.

2) FINDSTR mungkin gagal menemukan file jika nama tersebut berisi karakter ASCII yang diperluas dan nama file ditentukan pada baris perintah. Jika file yang akan dicari berisi ASCII yang diperluas dalam nama, maka file/F:FILE opsi tersebut harus digunakan.

Berikut adalah daftar lengkap transformasi karakter ASCII yang diperluas yang dilakukan FINDSTR pada string baris perintah. Setiap karakter direpresentasikan sebagai nilai kode byte desimal. Kode pertama mewakili karakter seperti yang disediakan pada baris perintah, dan kode kedua mewakili karakter yang diubahnya. Catatan - daftar ini dikompilasi di mesin AS. Saya tidak tahu apa dampak bahasa lain pada daftar ini.

158 treated as 080     199 treated as 221     226 treated as 071
169 treated as 170     200 treated as 043     227 treated as 112
176 treated as 221     201 treated as 043     228 treated as 083
177 treated as 221     202 treated as 045     229 treated as 115
178 treated as 221     203 treated as 045     231 treated as 116
179 treated as 221     204 treated as 221     232 treated as 070
180 treated as 221     205 treated as 045     233 treated as 084
181 treated as 221     206 treated as 043     234 treated as 079
182 treated as 221     207 treated as 045     235 treated as 100
183 treated as 043     208 treated as 045     236 treated as 056
184 treated as 043     209 treated as 045     237 treated as 102
185 treated as 221     210 treated as 045     238 treated as 101
186 treated as 221     211 treated as 043     239 treated as 110
187 treated as 043     212 treated as 043     240 treated as 061
188 treated as 043     213 treated as 043     242 treated as 061
189 treated as 043     214 treated as 043     243 treated as 061
190 treated as 043     215 treated as 043     244 treated as 040
191 treated as 043     216 treated as 043     245 treated as 041
192 treated as 043     217 treated as 043     247 treated as 126
193 treated as 045     218 treated as 043     249 treated as 250
194 treated as 045     219 treated as 221     251 treated as 118
195 treated as 043     220 treated as 095     252 treated as 110
196 treated as 045     222 treated as 221     254 treated as 221
197 treated as 043     223 treated as 095
198 treated as 221     224 treated as 097

Karakter apa pun> 0 yang tidak ada dalam daftar di atas diperlakukan sebagai dirinya sendiri, termasuk <CR>dan < LF>. Cara termudah untuk memasukkan karakter aneh seperti <CR>dan <LF>adalah memasukkannya ke dalam variabel lingkungan dan menggunakan ekspansi yang tertunda dalam argumen baris perintah.

Batas karakter untuk string yang ditemukan dalam file yang ditentukan oleh / G: FILE dan / F: opsi FILE
Karakter nul (0x00) dapat muncul dalam file, tetapi berfungsi seperti terminator string C. Setiap karakter setelah karakter nul diperlakukan sebagai string yang berbeda seolah-olah mereka berada di baris lain.

The <CR>dan <LF>karakter diperlakukan sebagai terminator garis yang mengakhiri string, dan tidak termasuk dalam string.

Semua karakter byte tunggal lainnya dimasukkan dengan sempurna dalam string.

Mencari file Unicode
FINDSTR tidak dapat mencari dengan benar sebagian besar Unicode (UTF-16, UTF-16LE, UTF-16BE, UTF-32) karena tidak dapat mencari nul byte dan Unicode biasanya berisi banyak nul byte.

Namun, perintah TYPE mengubah UTF-16LE dengan BOM ke set karakter byte tunggal, jadi perintah seperti berikut ini akan bekerja dengan UTF-16LE dengan BOM.

type unicode.txt|findstr "search"

Perhatikan bahwa titik kode Unicode yang tidak didukung oleh halaman kode aktif Anda akan dikonversi menjadi ?karakter.

Dimungkinkan untuk mencari UTF-8 selama string pencarian Anda hanya mengandung ASCII. Namun, output konsol karakter multi-byte UTF-8 tidak akan benar. Tetapi jika Anda mengarahkan output ke file, maka hasilnya akan dikodekan dengan benar UTF-8. Perhatikan bahwa jika file UTF-8 berisi BOM, maka BOM akan dianggap sebagai bagian dari baris pertama, yang dapat membuang pencarian yang cocok dengan awal baris.

Dimungkinkan untuk mencari multi-byte karakter UTF-8 jika Anda meletakkan string pencarian Anda dalam file pencarian yang dikodekan UTF-8 (tanpa BOM), dan menggunakan opsi / G.

End Of Line
FINDSTR memecah garis segera setelah setiap <LF>. Ada atau tidaknya <CR> tidak berdampak pada jeda baris.

Mencari lintas jeda
Seperti yang diharapkan, .metacharacter regex tidak akan cocok dengan <CR> atau <LF>. Tetapi dimungkinkan untuk mencari melintasi jeda baris menggunakan string pencarian baris perintah. Karakter <CR> dan <LF> harus dicocokkan secara eksplisit. Jika kecocokan multi-baris ditemukan, hanya baris pertama dari kecocokan yang dicetak. FINDSTR kemudian menggandakan kembali ke baris ke-2 di sumber dan memulai pencarian lagi - semacam fitur tipe "lihat ke depan".

Asumsikan TEXT.TXT memiliki konten ini (bisa gaya Unix atau Windows)

A
A
A
B
A
A

Lalu skrip ini

@echo off
setlocal
::Define LF variable containing a linefeed (0x0A)
set LF=^


::Above 2 blank lines are critical - do not remove

::Define CR variable containing a carriage return (0x0D)
for /f %%a in ('copy /Z "%~dpf0" nul') do set "CR=%%a"

setlocal enableDelayedExpansion
::regex "!CR!*!LF!" will match both Unix and Windows style End-Of-Line
findstr /n /r /c:"A!CR!*!LF!A" TEST.TXT

memberikan hasil ini

1:A
2:A
5:A

Pencarian lintas baris menggunakan opsi / G: FILE tidak tepat karena satu-satunya cara untuk mencocokkan <CR> atau <LF> adalah melalui ekspresi rentang kelas karakter regex yang mengapit karakter EOL.

  • [<TAB>-<0x0B>] cocok dengan <LF>, tetapi juga cocok dengan <TAB> dan <0x0B>

  • [<0x0C>-!] cocok dengan <CR>, tetapi juga cocok dengan <0x0C> dan!

    Catatan - di atas adalah representasi simbolis dari aliran byte regex karena saya tidak dapat secara grafis mewakili karakter.

Jawab dilanjutkan di bagian 2 di bawah ...

dbenham
sumber
46
Kelengkapan luar biasa. Kalau saja semua jawaban di internet seperti ini.
Mike Viens
1
kami mengalami masalah dengan addpath.batdari Q141344 dan findstr, yang mungkin terkait dengan masalah gantung Win7 yang disebutkan di atas. Saya telah membuat ruang obrolan untuk mencoba dan melacaknya, untuk siapa saja yang tertarik: chat.stackoverflow.com/rooms/13177/…
matt wilkie
2
EDIT - Tampilan karakter kontrol yang digambarkan sebagai titik-titik pada XP. Juga didokumentasikan disadap /Sdan /Dopsi yang berasal dari nama file 8,3 pendek.
dbenham
1
EDIT - 1) Nama file dalam file yang ditentukan oleh / F: FILE tidak boleh dikutip. 2) Transformasi karakter ASCII yang diperluas mempengaruhi string pencarian dan nama file ketika diberikan pada baris perintah.
dbenham
1
EDIT - Menambahkan bug di mana baris terakhir dari input pipa diabaikan jika terdiri dari satu karakter tanpa<LF>
dbenham
64

Jawaban dilanjutkan dari bagian 1 di atas - Saya sudah mengalami batas jawaban 30.000 karakter :-(

Dukungan Ekspresi Reguler Terbatas (regex)
terbatas Dukungan FINDSTR untuk ekspresi reguler sangat terbatas. Jika tidak ada dalam dokumentasi BANTUAN, itu tidak didukung.

Di luar itu, ekspresi regex yang didukung diimplementasikan dengan cara yang sama sekali tidak standar, sehingga hasilnya bisa berbeda maka akan diharapkan berasal dari sesuatu seperti grep atau perl.

Jangkar Posisi Garis Regex ^ dan $
^ cocok dengan awal aliran input serta posisi apa pun segera setelah <LF>. Karena FINDSTR juga memecah baris setelah <LF>, regex sederhana "^" akan selalu cocok dengan semua baris dalam file, bahkan file biner.

$cocok dengan posisi apa pun segera sebelum <CR>. Ini berarti bahwa string pencarian regex yang mengandung $tidak akan pernah cocok dengan baris apa pun dalam file teks gaya Unix, juga tidak akan cocok dengan baris terakhir file teks Windows jika tidak ada penanda EOL dari <CR> <LF>.

Catatan - Seperti dibahas sebelumnya, masukan yang dialihkan dan dialihkan ke FINDSTR mungkin telah <CR><LF>ditambahkan yang tidak ada dalam sumber. Jelas ini dapat memengaruhi pencarian regex yang menggunakan $.

String pencarian apa pun dengan karakter sebelum ^atau sesudahnya $akan selalu gagal menemukan kecocokan.

Opsi Posisi / B / E / X
Opsi posisi bekerja sama dengan ^dan $, kecuali mereka juga berfungsi untuk string pencarian literal.

/ B berfungsi sama seperti ^pada awal string pencarian regex.

/ E berfungsi sama seperti $pada akhir string pencarian regex.

/ X berfungsi sama seperti memiliki keduanya ^di awal dan $di akhir string pencarian regex.

Batas kata
\< regex haruslah istilah pertama di regex. Regex tidak akan cocok dengan apa pun jika ada karakter lain yang mendahuluinya. \<sesuai dengan awal input, awal baris (posisi segera setelah <LF>), atau posisi segera setelah karakter "non-kata". Karakter selanjutnya tidak harus berupa karakter "kata".

\>harus menjadi istilah terakhir di regex. Regex tidak akan cocok dengan apa pun jika ada karakter lain yang mengikutinya. \>sesuai dengan akhir input, posisi segera sebelum <CR>, atau posisi segera sebelum karakter "non-kata". Karakter sebelumnya tidak harus berupa karakter "kata".

Berikut adalah daftar lengkap karakter "non-kata", direpresentasikan sebagai kode byte desimal. Catatan - daftar ini dikompilasi di mesin AS. Saya tidak tahu apa dampak bahasa lain pada daftar ini.

001   028   063   179   204   230
002   029   064   180   205   231
003   030   091   181   206   232
004   031   092   182   207   233
005   032   093   183   208   234
006   033   094   184   209   235
007   034   096   185   210   236
008   035   123   186   211   237
009   036   124   187   212   238
011   037   125   188   213   239
012   038   126   189   214   240
014   039   127   190   215   241
015   040   155   191   216   242
016   041   156   192   217   243
017   042   157   193   218   244
018   043   158   194   219   245
019   044   168   195   220   246
020   045   169   196   221   247
021   046   170   197   222   248
022   047   173   198   223   249
023   058   174   199   224   250
024   059   175   200   226   251
025   060   176   201   227   254
026   061   177   202   228   255
027   062   178   203   229

Rentang kelas karakter Regex [xy]
Rentang kelas karakter tidak berfungsi seperti yang diharapkan. Lihat pertanyaan ini: Mengapa findstr tidak menangani case dengan benar (dalam beberapa keadaan)? , bersama dengan jawaban ini: https://stackoverflow.com/a/8767815/1012053 .

Masalahnya adalah FINDSTR tidak menyusun karakter dengan nilai kode byte mereka (biasanya dianggap sebagai kode ASCII, tetapi ASCII hanya didefinisikan dari 0x00 - 0x7F). Sebagian besar implementasi regex akan memperlakukan [AZ] sebagai huruf kapital semua huruf Inggris. Tetapi FINDSTR menggunakan urutan pemeriksaan yang kira-kira sesuai dengan cara kerja SORT. Jadi [AZ] termasuk alfabet Inggris lengkap, baik huruf besar dan kecil (kecuali untuk "a"), serta karakter alfa non-Inggris dengan diakritik.

Di bawah ini adalah daftar lengkap semua karakter yang didukung oleh FINDSTR, diurutkan dalam urutan pemeriksaan yang digunakan oleh FINDSTR untuk menetapkan rentang kelas karakter regex. Karakter direpresentasikan sebagai nilai kode byte desimal mereka. Saya percaya urutan pemeriksaan masuk akal jika karakter dilihat menggunakan kode halaman 437. Catatan - daftar ini dikompilasi pada mesin AS. Saya tidak tahu apa dampak bahasa lain pada daftar ini.

001
002
003
004
005
006
007
008
014
015
016
017
018           
019
020
021
022
023
024
025
026
027
028
029
030
031
127
039
045
032
255
009
010
011
012
013
033
034
035
036
037
038
040
041
042
044
046
047
058
059
063
064
091
092
093
094
095
096
123
124
125
126
173
168
155
156
157
158
043
249
060
061
062
241
174
175
246
251
239
247
240
243
242
169
244
245
254
196
205
179
186
218
213
214
201
191
184
183
187
192
212
211
200
217
190
189
188
195
198
199
204
180
181
182
185
194
209
210
203
193
207
208
202
197
216
215
206
223
220
221
222
219
176
177
178
170
248
230
250
048
172
171
049
050
253
051
052
053
054
055
056
057
236
097
065
166
160
133
131
132
142
134
143
145
146
098
066
099
067
135
128
100
068
101
069
130
144
138
136
137
102
070
159
103
071
104
072
105
073
161
141
140
139
106
074
107
075
108
076
109
077
110
252
078
164
165
111
079
167
162
149
147
148
153
112
080
113
081
114
082
115
083
225
116
084
117
085
163
151
150
129
154
118
086
119
087
120
088
121
089
152
122
090
224
226
235
238
233
227
229
228
231
237
232
234

Batas jangka kelas karakter
regex dan BUG Tidak hanya FINDSTR dibatasi hingga maksimum 15 syarat kelas karakter dalam suatu regex, ia gagal menangani upaya untuk melampaui batas dengan benar. Menggunakan 16 atau lebih istilah kelas karakter menghasilkan jendela pop-up interaktif yang menyatakan "Utilitas Cari String (QGREP) telah mengalami masalah dan harus ditutup. Kami mohon maaf atas ketidaknyamanan ini." Teks pesan sedikit berbeda tergantung pada versi Windows. Berikut adalah salah satu contoh FINDSTR yang akan gagal:

echo 01234567890123456|findstr [0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]

Bug ini dilaporkan oleh pengguna DosTips Judago di sini . Ini telah dikonfirmasi pada XP, Vista, dan Windows 7.

Pencarian regex gagal (dan mungkin hang tanpa batas) jika mereka memasukkan kode byte 0xFF (desimal 255)
Setiap pencarian regex yang menyertakan kode byte 0xFF (desimal 255) akan gagal. Gagal jika kode byte 0xFF disertakan secara langsung, atau jika secara implisit termasuk dalam rentang kelas karakter. Ingat bahwa rentang kelas karakter FINDSTR tidak menyusun karakter berdasarkan nilai kode byte. Karakter <0xFF>muncul relatif awal dalam urutan susunan antara karakter <space>dan <tab>. Jadi rentang kelas karakter apa pun yang mencakup keduanya <space>dan <tab>akan gagal.

Perilaku tepatnya berubah sedikit tergantung pada versi Windows. Windows 7 hang tanpa batas jika 0xFF disertakan. XP tidak hang, tetapi selalu gagal menemukan kecocokan, dan kadang-kadang mencetak pesan kesalahan berikut - "Proses mencoba menulis ke pipa yang tidak ada."

Saya tidak lagi memiliki akses ke mesin Vista, jadi saya belum dapat menguji pada Vista.

Regex bug: .dan [^anySet]dapat mencocokkan End-Of-File
The regex .meta-karakter hanya harus sesuai karakter apapun selain <CR>atau <LF>. Ada bug yang memungkinkannya untuk mencocokkan End-Of-File jika baris terakhir dalam file tidak dihentikan oleh <CR>atau <LF>. Namun, .tidak akan cocok dengan file kosong.

Misalnya, file bernama "test.txt" yang berisi satu baris x, tanpa mengakhiri <CR>atau <LF>, akan cocok dengan yang berikut:

findstr /r x......... test.txt

Bug ini telah dikonfirmasi pada XP dan Win7.

Hal yang sama tampaknya berlaku untuk set karakter negatif. Sesuatu seperti [^abc]akan cocok dengan End-Of-File. Set karakter positif suka[abc] sepertinya berfungsi dengan baik. Saya hanya menguji ini pada Win7.

dbenham
sumber
1
findstr juga bermasalah berurusan dengan file besar. File> 2GB dapat menyebabkan findstr hang. Itu tidak selalu terjadi. Dalam mengkonfirmasi bug saya mencari file yang 2.3GB yang tidak hang. Itu hang bahkan jika mencari hanya satu file. Solusinya adalah menyalurkan output typeke findstr.
Disillusioned
Itu mungkin juga secara eksplisit menyebutkan secara eksplisit yang findstrmendukung banyak /c:string pencarian. Saya tahu jawaban Anda menunjukkan hal ini. Tetapi itu adalah sesuatu yang tidak didokumentasikan; dan saya cukup terkejut mengetahui fitur tersebut setelah digunakan findstrtanpanya selama beberapa tahun.
Disillusioned
@CraigYoung - Anda benar tentang sumber string pencarian. Saya mengedit jawaban saya, terima kasih.
dbenham
1
Pada penyelidikan lebih lanjut, sepertinya ada variasi pada LFmasalah yang Anda dokumentasikan. Saya menyadari file pengujian saya tidak berakhir LFkarena saya gunakan copydalam mode append untuk membuatnya. Saya telah menempatkan sesi baris perintah untuk menunjukkan masalah menjadi jawaban ( stackoverflow.com/a/22943056/224704 ). Perhatikan bahwa input tidak dialihkan, namun pencarian hang. Perintah pencarian yang sama persis tidak hang dengan file yang lebih kecil yang sama tidak berakhir dengan LF.
Disillusioned
1
Temuan baru (Win7): findstr /R /C:"^[0-9][0-9]* [0-3][0-9][0-9]-[0-9][0-9]:[0-5][0-9]:[0-5][0-9]\.[0-9][0-9]* [0-9]*\.[0-9]*"(15 kelas karakter) - ErrorLevel = -1073740791 (0xC0000409), kesalahan jendela dialog : Find String (QGREP) Utility has stopped working; setelah menghapus satu atau dua karakter meta kelas ( *\.), berfungsi ...
aschipfl
7

findstr terkadang hang tiba-tiba ketika mencari file besar.

Saya belum mengkonfirmasi kondisi atau ukuran batas yang tepat. Saya menduga file apa pun yang lebih besar 2GB mungkin berisiko.

Saya memiliki pengalaman yang beragam dengan ini, jadi ini lebih dari sekedar ukuran file. Ini sepertinya merupakan variasi pada FINDSTR yang tergantung pada XP dan Windows 7 jika input yang dialihkan tidak diakhiri dengan LF , tetapi seperti yang diperlihatkan masalah khusus ini muncul ketika input tidak dialihkan.

Sesi baris perintah berikut (Windows 7) menunjukkan bagaimana cara findstrmenggantung ketika mencari file 3GB.

C:\Data\Temp\2014-04>echo 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890> T100B.txt

C:\Data\Temp\2014-04>for /L %i in (1,1,10) do @type T100B.txt >> T1KB.txt

C:\Data\Temp\2014-04>for /L %i in (1,1,1000) do @type T1KB.txt >> T1MB.txt

C:\Data\Temp\2014-04>for /L %i in (1,1,1000) do @type T1MB.txt >> T1GB.txt

C:\Data\Temp\2014-04>echo find this line>> T1GB.txt

C:\Data\Temp\2014-04>copy T1GB.txt + T1GB.txt + T1GB.txt T3GB.txt
T1GB.txt
T1GB.txt
T1GB.txt
        1 file(s) copied.

C:\Data\Temp\2014-04>dir
 Volume in drive C has no label.
 Volume Serial Number is D2B2-FFDF

 Directory of C:\Data\Temp\2014-04

2014/04/08  04:28 PM    <DIR>          .
2014/04/08  04:28 PM    <DIR>          ..
2014/04/08  04:22 PM               102 T100B.txt
2014/04/08  04:28 PM     1 020 000 016 T1GB.txt
2014/04/08  04:23 PM             1 020 T1KB.txt
2014/04/08  04:23 PM         1 020 000 T1MB.txt
2014/04/08  04:29 PM     3 060 000 049 T3GB.txt
               5 File(s)  4 081 021 187 bytes
               2 Dir(s)  51 881 050 112 bytes free
C:\Data\Temp\2014-04>rem Findstr on the 1GB file does not hang

C:\Data\Temp\2014-04>findstr "this" T1GB.txt
find this line

C:\Data\Temp\2014-04>rem On the 3GB file, findstr hangs and must be aborted... even though it clearly reaches end of file

C:\Data\Temp\2014-04>findstr "this" T3GB.txt
find this line
find this line
find this line
^C
C:\Data\Temp\2014-04>

Catatan, saya telah memverifikasi dalam hex editor yang semua barisnya diakhiri CRLF. Satu-satunya anomali adalah bahwa file tersebut diakhiri dengan 0x1Akarena cara copykerja . Namun perlu dicatat, bahwa anomali ini tidak menyebabkan masalah pada file "kecil" .

Dengan pengujian tambahan, saya telah mengkonfirmasi yang berikut:

  • Menggunakan copydengan /bopsi untuk file biner mencegah penambahan 0x1Akarakter, dan findstrtidak menggantung pada file 3GB.
  • Mengakhiri file 3GB dengan karakter berbeda juga menyebabkan findstrhang.
  • Itu 0x1A karakter tidak menimbulkan masalah pada file "kecil". (Demikian pula untuk karakter penghentian lainnya.)
  • Menambahkan CRLF setelah 0x1Amenyelesaikan masalah. ( LFdengan sendirinya mungkin sudah cukup.)
  • Menggunakan type untuk mem-pipe file menjadi findstrkarya tanpa menggantung. (Ini mungkin karena efek samping dari salah satu typeatau |yang memasukkan End Of Line tambahan.)
  • Menggunakan input yang dialihkan <juga menyebabkan findstrhang. Tapi ini diharapkan; seperti yang dijelaskan dalam posting dbenham : "input yang dialihkan harus diakhiri dengan LF" .
Kecewa
sumber
1
+1, saya dapat mengonfirmasi masalah pada mesin Win7 saya. Sebuah file berukuran 2GiB tepatnya tergantung ketika karakter terakhir tidak <LF>. File dua byte lebih kecil tidak hang. Sangat jahat!
dbenham
6

Ketika beberapa perintah tertutup dalam tanda kurung dan ada file yang dialihkan ke seluruh blok:

< input.txt (
   command1
   command2
   . . .
) > output.txt

... maka file tetap terbuka selama perintah di blok aktif, sehingga perintah dapat memindahkan penunjuk file dari file yang diarahkan. Perintah MORE dan FIND memindahkan pointer file Stdin ke awal file sebelum memprosesnya, sehingga file yang sama dapat diproses beberapa kali di dalam blok. Misalnya, kode ini:

more < input.txt >  output.txt
more < input.txt >> output.txt

... menghasilkan hasil yang sama dari yang ini:

< input.txt (
   more
   more
) > output.txt

Kode ini:

find    "search string" < input.txt > matchedLines.txt
find /V "search string" < input.txt > unmatchedLines.txt

... menghasilkan hasil yang sama dari yang ini:

< input.txt (
   find    "search string" > matchedLines.txt
   find /V "search string" > unmatchedLines.txt
)

FINDSTR berbeda; itu tidak memindahkan penunjuk file Stdin dari posisi saat ini. Misalnya, kode ini menyisipkan baris baru setelah baris pencarian:

call :ProcessFile < input.txt
goto :EOF

:ProcessFile
   rem Read the next line from Stdin and copy it
   set /P line=
   echo %line%
   rem Test if it is the search line
   if "%line%" neq "search line" goto ProcessFile
rem Insert the new line at this point
echo New line
rem And copy the rest of lines
findstr "^"
exit /B

Kami dapat memanfaatkan fitur ini dengan baik dengan bantuan program tambahan yang memungkinkan kami untuk memindahkan penunjuk file dari file yang dialihkan, seperti yang ditunjukkan dalam contoh ini .

Perilaku ini pertama kali dilaporkan oleh jeb di posting ini .


EDIT 2018-08-18 : Bug FINDSTR baru dilaporkan

Perintah FINDSTR memiliki bug aneh yang terjadi ketika perintah ini digunakan untuk menampilkan karakter berwarna DAN output dari perintah tersebut dialihkan ke perangkat CON. Untuk detail tentang cara menggunakan perintah FINDSTR untuk menampilkan teks berwarna, lihat topik ini .

Ketika output dari bentuk perintah FINDSTR ini dialihkan ke CON, sesuatu yang aneh terjadi setelah teks dihasilkan dalam warna yang diinginkan: semua teks setelah itu output sebagai karakter "tidak terlihat", meskipun deskripsi yang lebih tepat adalah bahwa teks tersebut adalah output sebagai teks hitam di atas latar belakang hitam. Teks asli akan muncul jika Anda menggunakan perintah COLOR untuk mengatur ulang warna latar depan dan latar belakang dari seluruh layar. Namun, ketika teks "tidak terlihat" kita bisa menjalankan perintah SET / P, sehingga semua karakter yang dimasukkan tidak akan muncul di layar. Perilaku ini dapat digunakan untuk memasukkan kata sandi.

@echo off
setlocal

set /P "=_" < NUL > "Enter password"
findstr /A:1E /V "^$" "Enter password" NUL > CON
del "Enter password"
set /P "password="
cls
color 07
echo The password read is: "%password%"
Aacini
sumber
2

Saya ingin melaporkan bug mengenai bagian Sumber data untuk mencari di jawaban pertama saat menggunakan en dash (-) atau em dash (-) di dalam nama file.

Lebih khusus lagi, jika Anda akan menggunakan opsi pertama - nama file ditentukan sebagai argumen , file tidak akan ditemukan. Segera setelah Anda menggunakan opsi 2 - stdin melalui pengalihan atau 3 - aliran data dari pipa , findstr akan menemukan file.

Misalnya, skrip kumpulan sederhana ini:

echo off
chcp 1250 > nul
set INTEXTFILE1=filename with – dash.txt
set INTEXTFILE2=filename with — dash.txt

rem 3 way of findstr use with en dashed filename
echo.
echo Filename with en dash:
echo.
echo 1. As argument
findstr . "%INTEXTFILE1%"
echo.
echo 2. As stdin via redirection
findstr . < "%INTEXTFILE1%"
echo.
echo 3. As datastream from a pipe
type "%INTEXTFILE1%" | findstr .
echo.
echo.
rem The same set of operations with em dashed filename
echo Filename with em dash:
echo.
echo 1. As argument
findstr . "%INTEXTFILE2%"
echo.
echo 2. As stdin via redirection
findstr . < "%INTEXTFILE2%"
echo.
echo 3. As datastream from a pipe
type "%INTEXTFILE2%" | findstr .
echo.

pause

akan dicetak:

Nama file dengan tanda hubung:

  1. Sebagai argumen
    FINDSTR: Tidak dapat membuka nama file dengan - dash.txt

  2. Sebagai stdin melalui pengalihan,
    saya file dengan tanda hubung en.

  3. Sebagai datastream dari pipa
    saya file dengan tanda hubung en.

Nama file dengan tanda hubung:

  1. Sebagai argumen
    FINDSTR: Tidak dapat membuka nama file dengan - dash.txt

  2. Sebagai stdin melalui pengalihan
    saya file dengan tanda hubung em.

  3. Sebagai datastream dari pipa
    saya file dengan tanda hubung em.

Semoga ini bisa membantu.

M.

matro
sumber
1
Hai matro, sementara komentar Anda mungkin benar, saya tidak yakin mereka tidak menjawab pertanyaan yang sebenarnya.
Wai Ha Lee
Saya percaya ini adalah masalah unicode, yang tidak didukung FINDSTR. Pengalihan CMD.EXE dapat dengan benar membuka nama file dengan unicode, seperti halnya perintah TYPE. Tetapi di suatu tempat di sepanjang garis, FINDSTR mengubah en-dash dan em-dash ke dash normal, dan tentu saja OS tidak dapat menemukan nama itu. Jika Anda membuat file lain yang menggantikan tanda hubung untuk en-dash dan / atau em-dash, maka FINDSTR akan mencari file dasbor jika disediakan dengan nama yang berisi en-dash atau em-dash.
dbenham
Saya akan mengklasifikasikan masalah ini sebagai batasan daripada bug.
dbenham
Sebenarnya, ini bukan masalah unicode karena diperpanjang ASCII. Saya sudah mendokumentasikan masalah ini dalam jawaban asli saya di bawah judul Karakter batas untuk parameter baris perintah - Transformasi ASCII yang diperluas . FINDSTR mengubah sejumlah kode ASCII yang diperluas menjadi ASCII sejati yang "terkait", termasuk en-dash dan em-dash.
dbenham
1

The findstrperintah menetapkan ErrorLevel(atau kode keluar) ke salah satu dari nilai berikut, mengingat bahwa tidak ada switch tidak valid atau tidak kompatibel dan tidak ada string pencarian melebihi batas panjang berlaku:

  • 0 ketika setidaknya satu kecocokan ditemukan dalam satu baris di seluruh file yang ditentukan;
  • 1 jika tidak;

Garis dianggap mengandung kecocokan ketika:

  • tidak ada /Vopsi yang diberikan dan ekspresi pencarian muncul setidaknya sekali;
  • yang /Vopsi diberikan dan ekspresi pencarian tidak terjadi;

Ini berarti bahwa /Vopsi juga mengubah yang dikembalikan ErrorLevel, tetapi tidak hanya mengembalikannya!

Sebagai contoh, ketika Anda sudah mendapat file test.txtdengan dua garis, salah satu yang berisi string texttetapi yang lain tidak, baik findstr "text" "test.txt"dan findstr /V "text" "test.txt"mengembalikan ErrorLeveldari 0.

Pada dasarnya Anda dapat mengatakan: jika findstrmengembalikan paling tidak satu baris, ErrorLeveldiatur ke 0, yang lain menjadi 1.

Perhatikan bahwa /Mopsi tidak mempengaruhi ErrorLevelnilai, itu hanya mengubah output.

(Hanya demi kelengkapan: findperintah berperilaku dengan cara yang persis sama sehubungan dengan /Vopsi dan ErrorLevel; /Copsi tidak mempengaruhi ErrorLevel.)

aschipfl
sumber
1

FINDSTR memiliki bug warna yang saya gambarkan dan pecahkan di /superuser/1535810/is-there-a-better-way-to-mitigate-this-obscure-color-bug-when-piping-to -findstr / 1538802? noredirect = 1 # comment2339443_1538802

Untuk meringkas utas itu, bugnya adalah bahwa jika input disalurkan ke FINDSTR dalam blok kode yang diurung, sebaris kode warna ANSI escape, berhenti bekerja dalam perintah yang dieksekusi nanti. Contoh kode warna inline adalah: echo %magenta%Alert: Something bad happened%yellow%(di mana magenta dan kuning adalah vars yang didefinisikan sebelumnya dalam file .bat sebagai kode color escape ANSI yang sesuai).

Solusi awal saya adalah memanggil subrutin do-nothing setelah FINDSTR. Entah bagaimana panggilan atau pengembalian "reset" apa pun yang perlu diatur ulang.

Kemudian saya menemukan solusi lain yang mungkin lebih efisien: tempatkan frasa FINDSTR di dalam tanda kurung, seperti dalam contoh berikut: echo success | ( FINDSTR /R success ) Menempatkan frasa FINDSTR dalam blok kode bersarang tampaknya mengisolasi bug kode warna FINDSTR sehingga tidak akan mempengaruhi apa yang ada di luar sarang yang bersarang. blok. Mungkin teknik ini akan menyelesaikan beberapa efek samping FINDSTR yang tidak diinginkan juga .

Dolores Stevens
sumber
Great ditemukan. Tetapi aturan Anda dapat disederhanakan (setidaknya pada mesin Windows 10 perusahaan saya). FINDSTR mencegah semua urutan pelarian konsol berfungsi untuk perintah berikutnya dalam blok perintah yang sama. Tidak masalah jika FINDSTR membaca pipa, input yang dialihkan, atau file. Kegagalan urutan keluar tidak terbatas pada kode warna. Blok perintah adalah setiap rangkaian perintah di dalam tanda kurung, dan / atau perintah digabungkan melalui &, &&, atau ||
dbenham
@ Benham: Generalisasi masalah yang bagus. Apakah Anda tahu apakah solusi saya - menggunakan frasa FINDSTR di dalam tanda kurung - juga berfungsi dalam kasus umum? Dan tahukah Anda apakah solusi saya memiliki efek samping yang tidak diinginkan?
Dolores Stevens
Saya tidak melakukan pengujian menyeluruh, tapi ya, tanda kurung bersarang tampaknya menjadi solusi umum, dan saya tidak bisa memikirkan kemungkinan efek samping yang tidak diinginkan.
dbenham
-1

/ D tip untuk banyak direktori: letakkan daftar direktori Anda sebelum string pencarian. Ini semua bekerja:

findstr /D:dir1;dir2 "searchString" *.*
findstr /D:"dir1;dir2" "searchString" *.*
findstr /D:"\path\dir1\;\path\dir2\" "searchString" *.*

Seperti yang diharapkan, jalur relatif ke lokasi jika Anda tidak memulai direktori \. Mengitari lintasan dengan "adalah opsional jika tidak ada spasi dalam nama direktori. Penutupnya \adalah opsional. Output dari lokasi akan mencakup jalur apa pun yang Anda berikan. Ini akan bekerja dengan atau tanpa mengelilingi daftar direktori ".

Gordon
sumber
Saya tidak melihat sesuatu yang tidak berdokumen di sini. Opsi / D dijelaskan dalam bantuan bawaan. Ini bukan pertanyaan untuk tips umum tentang cara menggunakan FINDSTR. Ini dimaksudkan untuk mencantumkan fitur, batasan, dan / atau bug yang tidak berdokumen.
dbenham
1
@ Benben benar itu tidak benar-benar tidak berdokumen, tapi saya menemukan saya harus dicker dengan findstr untuk mendapatkan hasil yang saya inginkan dan saya membagikan apa yang saya temukan DID bekerja sehingga orang tidak akan membuang waktu untuk bereksperimen dengan perintah yang TIDAK bekerja. hth (saya sedih Anda tidak suka input saya - itu hanya dimaksudkan untuk menjadi konstruktif)
gordon
IMHO saklar / D secara jelas dijelaskan dalam bantuan bawaan: /D:dirlist Search a semicolon-delimited list of directoriesdan ditempatkan sebelum string pencarian, jadi saya tidak mengerti apa sebenarnya yang "Anda temukan" tentang saklar / D (dan apa saja "perintah yang JANGAN bekerja ") ...
Aacini
@Aacini dalam banyak bahasa, urutan atribut tidak masalah. Saya mengerti dokumentasi untuk findstrdaftar / D terlebih dahulu. Ya saya tidak punya argumen dengan fitur yang didokumentasikan, hanya saja tidak didokumentasikan tentang gotcha bahwa urutan atribut penting. Saya melakukan pekerjaan commandline sangat sedikit, jadi ketika saya membuat perintah, tidak menyadari urutan membuat perbedaan, saya hanya menambahkan atribut ketika saya mendapatkannya (dan secara alfabet, C mendahului D). Saya menjadi benar-benar frustrasi dan telah berbagi pengalaman "ditemukan" saya untuk siapa pun yang tidak banyak bekerja dengan commandline.
gordon
1
Urutan atribut opsional biasanya tidak penting. The findstrdokumentasi menentukan bahwa stringsbagian ini tidak opsional dan bahwa Anda harus menempatkannya setelah opsional atribut dan sebelum opsional daftar nama file. Jika "Anda ditemukan" adalah bahwa menggunakan perintah tanpa mengikuti format penggunaannya menyebabkan kesalahan, maka titik tersebut didokumentasikan dengan baik. Lihat Perintah sintaks : "Sintaks muncul dalam urutan di mana Anda harus mengetik perintah dan parameter apa pun yang mengikutinya"
Aacini