Các tính năng và giới hạn không có giấy tờ của lệnh Windows FINDSTR là gì?


188

Lệnh Windows FINDSTR được ghi lại một cách khủng khiếp. Có sự trợ giúp dòng lệnh rất cơ bản có sẵn thông qua FINDSTR /?, hoặc HELP FINDSTR, nhưng nó không đầy đủ. Có thêm một chút tài liệu trực tuyến tại https://docs.microsoft.com/en-us/windows-server/adftime/windows-commands/findstr .

Có nhiều tính năng và giới hạn của FINDSTR thậm chí không được gợi ý trong tài liệu. Họ cũng không thể được dự đoán mà không có kiến ​​thức trước và / hoặc thử nghiệm cẩn thận.

Vì vậy, câu hỏi là - các tính năng và hạn chế của FINDSTR không có giấy tờ là gì?

Mục đích của câu hỏi này là cung cấp kho lưu trữ một cửa gồm nhiều tính năng không có giấy tờ để:

A) Các nhà phát triển có thể tận dụng tối đa các tính năng đang có.

B) Các nhà phát triển không lãng phí thời gian của họ để tự hỏi tại sao một cái gì đó không hoạt động khi nó có vẻ như nó nên.

Vui lòng đảm bảo rằng bạn biết các tài liệu hiện có trước khi trả lời. Nếu thông tin được bao phủ bởi TRỢ GIÚP, thì nó không thuộc về nơi này.

Đây cũng không phải là nơi để thể hiện những công dụng thú vị của FINDSTR. Nếu một người logic có thể dự đoán hành vi của việc sử dụng FINDSTR cụ thể dựa trên tài liệu, thì nó không thuộc về nơi này.

Dọc theo cùng một dòng, nếu một người logic có thể dự đoán hành vi của một cách sử dụng cụ thể dựa trên thông tin có trong bất kỳ câu trả lời hiện có, thì một lần nữa, nó không thuộc về nơi này.


15
Hoặc cách khác, bạn có thể mương tiện ích MS không có giấy tờ không hấp dẫn hoàn toàn và cài đặt / sử dụng grepđang rất được hiểu rõ và ghi nhận :-) Xem stackoverflow.com/questions/2635740/... ví dụ.
paxdiablo

17
Bằng mọi cách, nếu bạn đang ở trong một vị trí để sử dụng một cái gì đó ngoài FINDSTR, thì điều đó rất được khuyến khích. Nhưng một số người ở trong môi trường mà các tiện ích của bên thứ 3 bị cấm.
dbenham

4
Không có sự xúc phạm nào. Tôi nghiêm túc xem xét đưa vào từ chối trách nhiệm FINDSTR của riêng tôi tương tự như nhận xét của bạn! :)
dbenham

41
Tôi bị sốc và thất vọng ai đó sẽ tìm thấy câu hỏi này "Không mang tính xây dựng" và bỏ phiếu để đóng. Rất nhiều suy nghĩ đã đi vào câu hỏi cụ thể để tránh "ý kiến, tranh luận, tranh luận, bỏ phiếu hoặc thảo luận mở rộng". Câu hỏi đã được đăng trong 3,5 tháng, và không có bất kỳ tiêu cực nào được trích dẫn đã xảy ra. Câu trả lời được ghép nối chứa đầy sự thật, và cần nhiều giờ nghiên cứu và thử nghiệm.
dbenham

6
Một số độc giả có thể quan tâm đến bối cảnh lịch sử của lệnh findstr: blog.msdn.com/b/oldnewthing/archive/2012/11/11/10372436.aspx
Harry Johnston

Câu trả lời:


279

Lời nói đầu
Phần lớn thông tin trong câu trả lời này đã được thu thập dựa trên các thử nghiệm chạy trên máy Vista. Trừ khi có quy định rõ ràng khác, tôi chưa xác nhận liệu thông tin có áp dụng cho các phiên bản Windows khác hay không.

Đầu ra FINDSTR
Tài liệu không bao giờ làm phiền để giải thích đầu ra của FINDSTR. Nó ám chỉ thực tế là các dòng phù hợp được in, nhưng không có gì hơn.

Định dạng của đầu ra dòng phù hợp như sau:

tên tệp: lineNumber: line Offerset: text

Ở đâu

fileName: = Tên của tệp chứa dòng phù hợp. Tên tệp không được in nếu yêu cầu rõ ràng cho một tệp hoặc nếu tìm kiếm đầu vào có đường ống hoặc đầu vào được chuyển hướng. Khi được in, fileName sẽ luôn bao gồm bất kỳ thông tin đường dẫn nào được cung cấp. Thông tin đường dẫn bổ sung sẽ được thêm vào nếu/Stùy chọn được sử dụng. Đường dẫn được in luôn liên quan đến đường dẫn được cung cấp hoặc liên quan đến thư mục hiện tại nếu không được cung cấp.

Lưu ý - Có thể tránh tiền tố tên tệp khi tìm kiếm nhiều tệp bằng cách sử dụng các ký tự đại diện không chuẩn (và tài liệu kém) <>. Các quy tắc chính xác cho cách thức hoạt động của các ký tự đại diện ở đây . Cuối cùng, bạn có thể xem ví dụ này về cách các ký tự đại diện không chuẩn hoạt động với FINDSTR .

lineNumber: = Số dòng của dòng khớp được biểu thị dưới dạng giá trị thập phân với 1 đại diện cho dòng đầu tiên của đầu vào. Chỉ in nếu/Ntùy chọn được chỉ định.

linePackset: = Độ lệch byte thập phân của điểm bắt đầu của dòng khớp, với 0 đại diện cho ký tự đầu tiên của dòng thứ nhất. Chỉ in nếu/Otùy chọn được chỉ định. Đây không phải làphần bù của trận đấu trong dòng. Đó là số byte từ đầu tệp đến đầu dòng.

text = Biểu diễn nhị phân của dòng khớp, bao gồm mọi <CR> và / hoặc <LF>. Không có gì bị bỏ sót ngoài đầu ra nhị phân, sao cho ví dụ này khớp với tất cả các dòng sẽ tạo ra một bản sao nhị phân chính xác của tệp gốc.

FINDSTR "^" FILE >FILE_COPY

Tùy chọn / A đặt màu của fileName:, lineNumber:, và line Offerset: chỉ xuất ra. Văn bản của dòng phù hợp luôn được xuất ra với màu bảng điều khiển hiện tại. Tùy chọn / A chỉ có hiệu lực khi đầu ra được hiển thị trực tiếp đến bàn điều khiển. Tùy chọn / A không có hiệu lực nếu đầu ra được chuyển hướng đến một tệp hoặc đường ống. Xem bản chỉnh sửa 2018-08-18 trong câu trả lời của Aacini để biết mô tả về hành vi lỗi khi đầu ra được chuyển hướng đến CON.

Hầu hết các ký tự điều khiển và nhiều ký tự ASCII mở rộng hiển thị dưới dạng dấu chấm trên XP
FINDSTR trên XP hiển thị hầu hết các ký tự điều khiển không in được từ các dòng khớp nhau dưới dạng dấu chấm (dấu chấm) trên màn hình. Các ký tự điều khiển sau đây là ngoại lệ; chúng tự hiển thị: Tab 0x09, 0x0A LineFeed, Tab dọc 0x0B, Nguồn cấp biểu mẫu 0x0C, Trả về vận chuyển 0x0D.

XP FINDSTR cũng chuyển đổi một số ký tự ASCII mở rộng thành dấu chấm. Các ký tự ASCII mở rộng hiển thị dưới dạng các chấm trên XP giống như các ký tự được chuyển đổi khi được cung cấp trên dòng lệnh. Xem phần "Giới hạn ký tự cho các tham số dòng lệnh - Chuyển đổi ASCII mở rộng" , ở phần sau của bài viết này

Các ký tự điều khiển và ASCII mở rộng không được chuyển đổi thành các dấu chấm trên XP nếu đầu ra được dẫn, chuyển hướng đến một tệp hoặc trong mệnh đề FOR ​​IN ().

Vista và Windows 7 luôn hiển thị tất cả các ký tự như chính chúng, không bao giờ là dấu chấm.

Mã trả về (ERRORLEVEL)

  • 0 (thành công)
    • Trận đấu được tìm thấy trong ít nhất một dòng của ít nhất một tệp.
  • 1 (thất bại)
    • Không có kết quả khớp nào được tìm thấy trong bất kỳ dòng nào của tập tin.
    • Màu không hợp lệ được chỉ định bởi /A:xxtùy chọn
  • 2 (lỗi)
    • Tùy chọn không tương thích /L/Rcả hai chỉ định
    • Thiếu đối số sau /A:, /F:, /C:, /D:, hoặc/G:
    • Tập tin được chỉ định bởi /F:filehoặc /G:filekhông tìm thấy
  • 255 (lỗi)

Nguồn dữ liệu để tìm kiếm (Được cập nhật dựa trên các thử nghiệm với Windows 7)
Findstr có thể tìm kiếm dữ liệu từ một trong các nguồn sau:

  • tên tệp được chỉ định làm đối số và / hoặc sử dụng /F:filetùy chọn.

  • stdin thông qua chuyển hướng findstr "searchString" <file

  • luồng dữ liệu từ một đường ống type file | findstr "searchString"

Đối số / tùy chọn được ưu tiên hơn chuyển hướng, trong đó ưu tiên hơn dữ liệu đường ống.

Đối số tên tệp và /F:filecó thể được kết hợp. Nhiều đối số tên tệp có thể được sử dụng. Nếu nhiều /F:filetùy chọn được chỉ định, thì chỉ có tùy chọn cuối cùng được sử dụng. Thẻ hoang dã được phép trong các đối số tên tệp, nhưng không nằm trong tệp được trỏ bởi /F:file.

Nguồn của chuỗi tìm kiếm (Được cập nhật dựa trên các thử nghiệm với Windows 7)
Các tùy chọn /G:file/C:stringcó thể được kết hợp. Nhiều /C:stringtùy chọn có thể được chỉ định. Nếu nhiều /G:filetùy chọn được chỉ định, thì chỉ có tùy chọn cuối cùng được sử dụng. Nếu một trong hai /G:filehoặc /C:stringđược sử dụng, thì tất cả các đối số không phải tùy chọn được coi là tệp để tìm kiếm. Nếu không /G:filecũng không /C:stringđược sử dụng, sau đó lập luận phi tùy chọn đầu tiên được coi là một không gian giới hạn danh sách các thuật ngữ tìm kiếm.

Tên tệp không được trích dẫn trong tệp khi sử dụng /F:FILEtùy chọn.
Tên tệp có thể chứa dấu cách và các ký tự đặc biệt khác. Hầu hết các lệnh yêu cầu tên tệp như vậy được trích dẫn. Nhưng /F:files.txttùy chọn FINDSTR yêu cầu tên tệp trong tệp.txt phải KHÔNG được trích dẫn. Các tập tin sẽ không được tìm thấy nếu tên được trích dẫn.

LGI - Tên tệp ngắn 8.3 có thể phá vỡ các tùy chọn /D/S
như với tất cả các lệnh Windows, FINDSTR sẽ cố gắng khớp cả tên dài và tên 8.3 ngắn khi tìm tệp để tìm kiếm. Giả sử thư mục hiện tại chứa các tệp không trống sau:

b1.txt
b.txt2
c.txt

Lệnh sau sẽ tìm thành công cả 3 tệp:

findstr /m "^" *.txt

b.txt2phù hợp vì tên ngắn tương ứng B9F64~1.TXTphù hợp. Điều này phù hợp với hành vi của tất cả các lệnh Windows khác.

Nhưng một lỗi với /D/Scác tùy chọn khiến các lệnh sau chỉ tìm thấyb1.txt

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

Lỗi này không b.txt2được tìm thấy, cũng như tất cả các tên tệp sắp xếp sau b.txt2trong cùng một thư mục. Các tập tin bổ sung sắp xếp trước, như a.txt, được tìm thấy. Các tệp bổ sung sắp xếp sau này, như d.txt, sẽ bị bỏ qua khi lỗi được kích hoạt.

Mỗi thư mục tìm kiếm được xử lý độc lập. Ví dụ: /Stùy chọn sẽ bắt đầu tìm kiếm thành công trong thư mục con sau khi không tìm thấy tệp trong phần cha mẹ, nhưng một khi lỗi khiến tên tệp ngắn bị bỏ sót ở trẻ, thì tất cả các tệp tiếp theo trong thư mục con đó cũng sẽ bị bỏ qua .

Các lệnh hoạt động không có lỗi nếu các tên tệp giống nhau được tạo trên một máy bị tắt thế hệ tên NTFS 8.3. Tất nhiên b.txt2sẽ không được tìm thấy, nhưng c.txtsẽ được tìm thấy đúng.

Không phải tất cả các tên ngắn kích hoạt lỗi. Tất cả các trường hợp về hành vi bị lỗi mà tôi đã thấy liên quan đến một phần mở rộng dài hơn 3 ký tự với một tên ngắn 8.3 bắt đầu giống như một tên bình thường không yêu cầu tên 8.3.

Lỗi này đã được xác nhận trên XP, Vista và Windows 7.

Ký tự không thể in và /Ptùy chọn
Các /Ptùy chọn gây FINDSTR để bỏ qua bất kỳ tập tin có chứa bất kỳ số thập phân mã byte sau:
0-7, 14-25, 27-31.

Nói cách khác, /Ptùy chọn sẽ chỉ bỏ qua các tệp có chứa các ký tự điều khiển không in được. Ký tự điều khiển là các mã nhỏ hơn hoặc bằng 31 (0x1F). FINDSTR coi các ký tự điều khiển sau là có thể in được:

 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)

Tất cả các ký tự điều khiển khác được coi là không thể in được, sự hiện diện của nó khiến /Ptùy chọn bỏ qua tệp.

Đầu vào đường ống và chuyển hướng có thể đã <CR><LF>nối thêm
Nếu đầu vào được dẫn vào và ký tự cuối cùng của luồng không <LF>, thì FINDSTR sẽ tự động nối <CR><LF>vào đầu vào. Điều này đã được xác nhận trên XP, Vista và Windows 7. (Tôi từng nghĩ rằng ống Windows chịu trách nhiệm sửa đổi đầu vào, nhưng tôi đã phát hiện ra rằng FINDSTR thực sự đang thực hiện sửa đổi.)

Điều này cũng đúng với đầu vào được chuyển hướng trên Vista. Nếu ký tự cuối cùng của tệp được sử dụng làm đầu vào được chuyển hướng thì không <LF>, FINDSTR sẽ tự động nối <CR><LF>vào đầu vào. Tuy nhiên, XP và Windows 7 không thay đổi đầu vào chuyển hướng.

FINDSTR bị treo trên XP và Windows 7 nếu đầu vào được chuyển hướng không kết thúc bằng<LF>
Đây là một "tính năng" khó chịu trên XP và Windows 7. Nếu ký tự cuối cùng của tệp được sử dụng làm đầu vào chuyển hướng không kết thúc <LF>, thì FINDSTR sẽ bị treo vô thời hạn một khi nó đến cuối tập tin chuyển hướng.

Dòng dữ liệu cuối cùng có thể bị bỏ qua nếu nó bao gồm một ký tự
Nếu đầu vào được đặt vào và dòng cuối cùng bao gồm một ký tự không được theo sau <LF>, thì FINDSTR hoàn toàn bỏ qua dòng cuối cùng.

Ví dụ - Lệnh đầu tiên có một ký tự duy nhất và không <LF>khớp, nhưng lệnh thứ hai có 2 ký tự hoạt động tốt, cũng như lệnh thứ ba có một ký tự kết thúc dòng mới.

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

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

> echo x| findstr "^"
x

Báo cáo bởi người dùng DosTips Sponge Belly tại lỗi findstr mới . Xác nhận trên XP, Windows 7 và Windows 8. Chưa nghe về Vista. (Tôi không còn có Vista để kiểm tra).

Cú pháp
tùy chọn Tùy chọn có thể được thêm tiền tố /hoặc - Tùy chọn có thể được nối sau một /hoặc -. Tuy nhiên, danh sách tùy chọn được nối có thể chứa tối đa một tùy chọn đa vi khuẩn như TẮT hoặc F:, và tùy chọn đa ký tự phải là tùy chọn cuối cùng trong danh sách.

Sau đây là tất cả các cách tương đương để diễn tả một trường hợp tìm kiếm regex không nhạy cảm cho bất kỳ dòng nào chứa cả "xin chào" và "tạm biệt" theo bất kỳ thứ tự nào

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

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

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

Giới hạn độ dài chuỗi tìm kiếm
Trên Vista, độ dài tối đa được phép cho một chuỗi tìm kiếm là 511 byte. Nếu bất kỳ chuỗi tìm kiếm nào vượt quá 511 thì kết quả là FINDSTR: Search string too long.lỗi với ERRORLEVEL 2.

Khi thực hiện tìm kiếm biểu thức chính quy, độ dài chuỗi tìm kiếm tối đa là 254. Biểu thức chính quy có độ dài từ 255 đến 511 sẽ dẫn đến FINDSTR: Out of memorylỗi với ERRORLEVEL 2. Độ dài biểu thức chính quy> 511 dẫn đến FINDSTR: Search string too long.lỗi.

Trên Windows XP, độ dài chuỗi tìm kiếm rõ ràng ngắn hơn. Lỗi Findstr: "Chuỗi tìm kiếm quá dài": Làm cách nào để trích xuất và khớp chuỗi con trong vòng lặp "for"? Giới hạn XP là 127 byte cho cả tìm kiếm theo nghĩa đen và regex.

Giới hạn độ dài dòng Các
tệp được chỉ định làm đối số dòng lệnh hoặc thông qua tùy chọn / F: FILE không có giới hạn độ dài dòng đã biết. Các tìm kiếm đã được chạy thành công đối với tệp 128 MB không chứa một <LF>.

Dữ liệu đường ống và đầu vào được chuyển hướng được giới hạn ở 8191 byte mỗi dòng. Giới hạn này là một "tính năng" của FINDSTR. Nó không phải là vốn có của đường ống hoặc chuyển hướng. TÌM KIẾM bằng cách sử dụng stdin chuyển hướng hoặc đầu vào đường ống sẽ không bao giờ khớp với bất kỳ dòng nào> = 8k byte. Các dòng> = 8k tạo thông báo lỗi tới stderr, nhưng ERRORLEVEL vẫn là 0 nếu chuỗi tìm kiếm được tìm thấy trong ít nhất một dòng của ít nhất một tệp.

Loại tìm kiếm
/C:"string" mặc định: Chữ và biểu thức chính quy - Mặc định là / L bằng chữ. Hoàn toàn kết hợp tùy chọn / L với / C: "chuỗi" chắc chắn hoạt động nhưng không cần thiết.

"string argument"- Mặc định phụ thuộc vào nội dung của chuỗi tìm kiếm đầu tiên. (Hãy nhớ rằng <dấu cách> được sử dụng để phân định các chuỗi tìm kiếm.) Nếu chuỗi tìm kiếm đầu tiên là một biểu thức chính quy hợp lệ có chứa ít nhất một ký tự meta không thoát, thì tất cả các chuỗi tìm kiếm được coi là biểu thức chính quy. Nếu không, tất cả các chuỗi tìm kiếm được coi là chữ. Ví dụ: "51.4 200"sẽ được coi là hai biểu thức chính quy bởi vì chuỗi đầu tiên chứa một dấu chấm không thoát, trong khi đó "200 51.4"sẽ được coi là hai chữ vì chuỗi đầu tiên không chứa bất kỳ ký tự meta nào.

/G:file- Mặc định phụ thuộc vào nội dung của dòng không trống đầu tiên trong tệp. Nếu chuỗi tìm kiếm đầu tiên là một biểu thức chính quy hợp lệ có chứa ít nhất một ký tự meta chưa thoát, thì tất cả các chuỗi tìm kiếm được coi là biểu thức chính quy. Nếu không, tất cả các chuỗi tìm kiếm được coi là chữ.

Khuyến nghị - Luôn chỉ định rõ ràng /Ltùy chọn bằng chữ hoặc /Rtùy chọn biểu thức chính quy khi sử dụng "string argument"hoặc /G:file.

LGI - Chỉ định nhiều chuỗi tìm kiếm theo nghĩa đen có thể cho kết quả không đáng tin cậy

Ví dụ FINDSTR đơn giản sau đây không tìm thấy kết quả khớp, mặc dù vậy.

echo ffffaaa|findstr /l "ffffaaa faffaffddd"

Lỗi này đã được xác nhận trên Windows Server 2003, Windows XP, Vista và Windows 7.

Dựa trên các thử nghiệm, FINDSTR có thể thất bại nếu tất cả các điều kiện sau được đáp ứng:

  • Tìm kiếm đang sử dụng nhiều chuỗi tìm kiếm theo nghĩa đen
  • Các chuỗi tìm kiếm có độ dài khác nhau
  • Chuỗi tìm kiếm ngắn có một số lượng trùng lặp với chuỗi tìm kiếm dài hơn
  • Tìm kiếm là trường hợp nhạy cảm (không có /Itùy chọn)

Trong mọi thất bại tôi đã thấy, nó luôn là một trong những chuỗi tìm kiếm ngắn hơn thất bại.

Để biết thêm thông tin, hãy xem Tại sao ví dụ FINDSTR này không có nhiều chuỗi tìm kiếm theo nghĩa đen tìm thấy sự trùng khớp?

Báo giá và phản hồi trong các đối số dòng lệnh
Lưu ý - Nhận xét của người dùng MC ND phản ánh các quy tắc phức tạp khủng khiếp thực sự cho phần này. Có 3 giai đoạn phân tích cú pháp riêng biệt liên quan:

  • Cmd.exe đầu tiên có thể yêu cầu một số trích dẫn được thoát là ^ "(thực sự không có gì để làm với FINDSTR)
  • FINDSTR tiếp theo sử dụng trình phân tích cú pháp đối số MS C / C ++ trước 2008 , có các quy tắc đặc biệt cho "và \
  • Sau khi trình phân tích cú pháp đối số kết thúc, FINDSTR còn xử lý thêm \ theo sau là một ký tự chữ và số dưới dạng chữ, nhưng \ theo sau là ký tự không phải là số-alpha dưới dạng ký tự thoát

Phần còn lại của phần được tô sáng này không chính xác 100%. Nó có thể phục vụ như một hướng dẫn cho nhiều tình huống, nhưng các quy tắc trên là cần thiết cho sự hiểu biết tổng thể.

Thoát trích dẫn trong chuỗi tìm kiếm dòng lệnh
Báo giá trong chuỗi tìm kiếm dòng lệnh phải được thoát với dấu gạch chéo ngược như thế nào \". Điều này đúng cho cả chuỗi tìm kiếm theo nghĩa đen và regex. Thông tin này đã được xác nhận trên XP, Vista và Windows 7.

Lưu ý: Báo giá cũng có thể cần phải được thoát cho trình phân tích cú pháp CMD.EXE, nhưng điều này không liên quan gì đến FINDSTR. Ví dụ: để tìm kiếm một trích dẫn bạn có thể sử dụng:

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

Thoát khỏi dấu gạch chéo ngược trong chuỗi tìm kiếm bằng chữ dòng lệnh
Dấu gạch chéo ngược trong chuỗi tìm kiếm bằng chữ thường có thể được biểu diễn dưới dạng \hoặc dưới dạng \\. Chúng thường tương đương. (Có thể có những trường hợp bất thường trong Vista khi dấu gạch chéo ngược phải luôn được thoát, nhưng tôi không còn máy Vista để kiểm tra nữa) .

Nhưng có một số trường hợp đặc biệt:

Khi tìm kiếm dấu gạch chéo ngược liên tiếp, tất cả ngoại trừ cuối cùng phải được thoát. Dấu gạch chéo ngược cuối cùng có thể được thoát.

  • \\có thể được mã hóa thành \\\hoặc\\\\
  • \\\có thể được mã hóa thành \\\\\hoặc\\\\\\

Tìm kiếm một hoặc nhiều dấu gạch chéo ngược trước khi trích dẫn là kỳ quái. Logic sẽ đề xuất rằng trích dẫn phải được thoát, và mỗi dấu gạch chéo ngược hàng đầu sẽ cần phải được thoát, nhưng điều này không hoạt động! Thay vào đó, mỗi dấu gạch chéo ngược hàng đầu phải được thoát hai lần và trích dẫn được thoát bình thường:

  • \" phải được mã hóa là \\\\\"
  • \\" phải được mã hóa là \\\\\\\\\"

Như đã lưu ý trước đó, một hoặc nhiều trích dẫn đã thoát cũng có thể yêu cầu thoát với ^trình phân tích cú pháp CMD

Thông tin trong phần này đã được xác nhận trên XP và Windows 7.

Thoát Backslash trong chuỗi tìm kiếm regex dòng lệnh

  • Chỉ dành cho Vista: Dấu gạch chéo ngược trong regex phải được thoát gấp đôi như thế \\\\hoặc nếu không thì thoát đơn lẻ trong một lớp ký tự như [\\]

  • XP và Windows 7: Dấu gạch chéo ngược trong regex luôn có thể được biểu diễn dưới dạng [\\]. Nó thường có thể được đại diện là \\. Nhưng điều này không bao giờ hoạt động nếu dấu gạch chéo ngược trước một trích dẫn thoát.

    Một hoặc nhiều dấu gạch chéo ngược trước khi trích dẫn thoát phải được thoát kép hoặc mã hóa khác là [\\]

    • \"có thể được mã hóa thành \\\\\"hoặc[\\]\"
    • \\"có thể được mã hóa như \\\\\\\\\"hoặc [\\][\\]\"hoặc\\[\\]\"

Thoát trích dẫn và dấu gạch chéo ngược trong / G: FILE chuỗi tìm kiếm theo nghĩa đen
Dấu ngoặc kép độc lập và dấu gạch chéo ngược trong tệp chuỗi tìm kiếm bằng chữ được chỉ định bởi / G: tệp không cần phải thoát, nhưng chúng có thể được thoát.

"\"là tương đương.

\\\là tương đương.

Nếu mục đích là tìm kiếm \, thì ít nhất dấu gạch chéo ngược hàng đầu phải được thoát. Cả hai \\\\\\\làm việc.

Nếu mục đích là tìm \ ", thì ít nhất dấu gạch chéo ngược hàng đầu phải được thoát. Cả hai \\"\\\"công việc.

Thoát trích dẫn và dấu gạch chéo ngược trong / G: FILE chuỗi tìm kiếm regex
Đây là trường hợp trong đó các chuỗi thoát hoạt động như mong đợi dựa trên tài liệu. Trích dẫn không phải là một metacharacter regex, vì vậy nó không cần phải thoát (nhưng có thể). Backslash là một metacharacter regex, vì vậy nó phải được thoát.

Giới hạn ký tự cho các tham số dòng lệnh - Chuyển đổi ASCII mở rộng Ký tự
null (0x00) không thể xuất hiện trong bất kỳ chuỗi nào trên dòng lệnh. Bất kỳ ký tự byte đơn nào khác có thể xuất hiện trong chuỗi (0x01 - 0xFF). Tuy nhiên, FINDSTR chuyển đổi nhiều ký tự ASCII mở rộng mà nó tìm thấy trong các tham số dòng lệnh thành các ký tự khác. Điều này có tác động lớn theo hai cách:

1) Nhiều ký tự ASCII mở rộng sẽ không khớp với nhau nếu được sử dụng làm chuỗi tìm kiếm trên dòng lệnh. Giới hạn này là giống nhau cho các tìm kiếm theo nghĩa đen và regex. Nếu một chuỗi tìm kiếm phải chứa ASCII mở rộng, thì /G:FILEtùy chọn nên được sử dụng thay thế.

2) FINDSTR có thể không tìm thấy tệp nếu tên chứa các ký tự ASCII mở rộng và tên tệp được chỉ định trên dòng lệnh. Nếu một tệp được tìm kiếm chứa ASCII mở rộng trong tên, thì /F:FILEtùy chọn nên được sử dụng thay thế.

Dưới đây là danh sách đầy đủ các phép biến đổi ký tự ASCII mở rộng mà FINDSTR thực hiện trên các chuỗi dòng lệnh. Mỗi ký tự được biểu diễn dưới dạng giá trị mã byte thập phân. Mã đầu tiên đại diện cho ký tự như được cung cấp trên dòng lệnh và mã thứ hai đại diện cho ký tự mà nó được chuyển đổi thành. Lưu ý - danh sách này được tổng hợp trên máy Hoa Kỳ. Tôi không biết những tác động khác mà các ngôn ngữ khác có thể có trong danh sách này.

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

Bất kỳ ký tự> 0 nào không có trong danh sách trên đều được coi là chính nó, bao gồm <CR>và < LF>. Cách dễ nhất để bao gồm các ký tự lẻ như <CR><LF>đưa chúng vào một biến môi trường và sử dụng mở rộng bị trì hoãn trong đối số dòng lệnh.

Giới hạn ký tự cho các chuỗi được tìm thấy trong các tệp được chỉ định bởi / G: FILE và / F: FILE Tùy chọn
nul (0x00) có thể xuất hiện trong tệp, nhưng nó hoạt động như bộ kết thúc chuỗi C. Bất kỳ ký tự nào sau một ký tự nul đều được coi là một chuỗi khác nhau như thể chúng ở trên một dòng khác.

Các ký tự <CR><LF>được coi là các đầu cuối dòng kết thúc một chuỗi và không được bao gồm trong chuỗi.

Tất cả các ký tự byte đơn khác được bao gồm hoàn hảo trong một chuỗi.

Tìm kiếm tệp Unicode
FINDSTR không thể tìm kiếm chính xác hầu hết Unicode (UTF-16, UTF-16LE, UTF-16BE, UTF-32) vì nó không thể tìm kiếm các byte nul và Unicode thường chứa nhiều byte nul.

Tuy nhiên, lệnh TYPE chuyển đổi UTF-16LE với BOM thành một bộ ký tự byte đơn, do đó, một lệnh như sau sẽ hoạt động với UTF-16LE với BOM.

type unicode.txt|findstr "search"

Lưu ý rằng các điểm mã Unicode không được trang mã hoạt động của bạn hỗ trợ sẽ được chuyển đổi thành các ?ký tự.

Có thể tìm kiếm UTF-8 miễn là chuỗi tìm kiếm của bạn chỉ chứa ASCII. Tuy nhiên, đầu ra giao diện điều khiển của bất kỳ ký tự UTF-8 nhiều byte nào sẽ không chính xác. Nhưng nếu bạn chuyển hướng đầu ra thành một tệp, thì kết quả sẽ được mã hóa chính xác UTF-8. Lưu ý rằng nếu tệp UTF-8 chứa BOM, thì BOM sẽ được coi là một phần của dòng đầu tiên, có thể loại bỏ tìm kiếm khớp với đầu dòng.

Có thể tìm kiếm các ký tự UTF-8 nhiều byte nếu bạn đặt chuỗi tìm kiếm của mình vào tệp tìm kiếm được mã hóa UTF-8 (không có BOM) và sử dụng tùy chọn / G.

Kết thúc dòng
FINDSTR ngắt dòng ngay lập tức sau mỗi <LF>. Sự hiện diện hay vắng mặt của <CR> không ảnh hưởng đến ngắt dòng.

Tìm kiếm trên các ngắt dòng
Như dự kiến, .metacharacter regex sẽ không khớp với <CR> hoặc <LF>. Nhưng có thể tìm kiếm trên một ngắt dòng bằng cách sử dụng chuỗi tìm kiếm dòng lệnh. Cả hai ký tự <CR> và <LF> phải được khớp rõ ràng. Nếu tìm thấy kết quả khớp nhiều dòng, chỉ dòng thứ 1 của trận đấu được in. FINDSTR sau đó nhân đôi trở lại dòng thứ 2 trong nguồn và bắt đầu tìm kiếm lại từ đầu - loại tính năng "nhìn về phía trước".

Giả sử TEXT.TXT có các nội dung này (có thể là kiểu Unix hoặc Windows)

A
A
A
B
A
A

Sau đó, kịch bản này

@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

cho những kết quả này

1:A
2:A
5:A

Tìm kiếm trên các ngắt dòng bằng tùy chọn / G: FILE là không chính xác vì cách duy nhất để khớp với <CR> hoặc <LF> là thông qua biểu thức phạm vi lớp ký tự regex kẹp các ký tự EOL.

  • [<TAB>-<0x0B>] khớp với <LF>, nhưng nó cũng khớp với <TAB> và <0x0B>

  • [<0x0C>-!] khớp với <CR>, nhưng nó cũng khớp với <0x0C> và!

    Lưu ý - ở trên là các biểu diễn tượng trưng của luồng byte regex vì tôi không thể biểu thị bằng các ký tự.

Trả lời tiếp tục trong phần 2 dưới đây ...


45
Hoàn thiện xuất sắc. Nếu chỉ có tất cả các câu trả lời trên internet là như thế này.
Mike Viens

1
chúng tôi đã gặp sự cố addpath.battừ Q141344 và findstr, có thể liên quan đến sự cố treo Win7 đã đề cập ở trên. Tôi đã tạo một phòng trò chuyện để thử và theo dõi điều này, cho bất kỳ ai quan tâm: chat.stackoverflow.com/rooms/13177/ mẹo
matt wilkie

2
EDIT - Mô tả hiển thị các ký tự điều khiển dưới dạng dấu chấm trên XP. Cũng ghi lại lỗi /S/Dcác tùy chọn xuất phát từ tên tệp 8.3 ngắn.
dbenham

1
EDIT - 1) Tên tệp trong tệp được chỉ định bởi / F: FILE không được trích dẫn. 2) Chuyển đổi các ký tự ASCII mở rộng ảnh hưởng đến cả chuỗi tìm kiếm và tên tệp khi được cung cấp trên dòng lệnh.
dbenham

1
EDIT - Đã thêm lỗi trong đó dòng cuối cùng của đầu vào đường ống bị bỏ qua nếu nó bao gồm một ký tự không có<LF>
dbenham

64

Trả lời tiếp tục từ phần 1 ở trên - Tôi đã chạy vào giới hạn câu trả lời 30.000 ký tự :-(

Giới hạn biểu thức chính quy (regex) Hỗ trợ
FINDSTR hỗ trợ cho biểu thức chính quy là rất hạn chế. Nếu nó không có trong tài liệu TRỢ GIÚP, nó không được hỗ trợ.

Ngoài ra, các biểu thức regex được hỗ trợ được triển khai theo cách hoàn toàn không chuẩn, sao cho kết quả có thể khác đi sau đó sẽ được dự kiến ​​đến từ một cái gì đó như grep hoặc perl.

Các neo vị trí dòng Regex ^ và $
^ khớp với đầu luồng đầu vào cũng như bất kỳ vị trí nào ngay sau <LF>. Vì FINDSTR cũng ngắt các dòng sau <LF>, một biểu thức đơn giản của "^" sẽ luôn khớp với tất cả các dòng trong một tệp, thậm chí là tệp nhị phân.

$phù hợp với bất kỳ vị trí nào ngay trước <CR>. Điều này có nghĩa là chuỗi tìm kiếm regex chứa $sẽ không bao giờ khớp với bất kỳ dòng nào trong tệp văn bản kiểu Unix, cũng không khớp với dòng cuối cùng của tệp văn bản Windows nếu thiếu dấu EOL của <CR> <LF>.

Lưu ý - Như đã thảo luận trước đây, đầu vào được chuyển hướng và chuyển hướng đến FINDSTR có thể đã <CR><LF>nối thêm mà không có trong nguồn. Rõ ràng điều này có thể tác động đến một tìm kiếm regex sử dụng $.

Bất kỳ chuỗi tìm kiếm nào có ký tự trước ^hoặc sau $sẽ luôn không tìm thấy kết quả khớp.

Tùy chọn vị trí / B / E / X
Các tùy chọn vị trí hoạt động giống như ^$, ngoại trừ chúng cũng hoạt động cho các chuỗi tìm kiếm theo nghĩa đen.

/ B hoạt động giống như khi ^bắt đầu chuỗi tìm kiếm regex.

/ E hoạt động giống như $ở cuối chuỗi tìm kiếm regex.

/ X hoạt động giống như có cả ^ở đầu và $cuối chuỗi tìm kiếm regex.

Ranh giới từ Regex
\< phải là thuật ngữ đầu tiên trong regex. Regex sẽ không khớp với bất cứ điều gì nếu có bất kỳ nhân vật nào khác đi trước nó. \<tương ứng với phần đầu của đầu vào, phần đầu của dòng (vị trí ngay sau dấu <LF>) hoặc vị trí ngay sau ký tự "không từ". Ký tự tiếp theo không cần phải là ký tự "từ".

\>phải là thuật ngữ cuối cùng trong regex. Regex sẽ không khớp với bất cứ điều gì nếu có bất kỳ nhân vật nào khác theo dõi nó. \>tương ứng với phần cuối của đầu vào, vị trí ngay trước dấu <CR> hoặc vị trí ngay trước bất kỳ ký tự "không từ" nào. Ký tự trước không cần phải là ký tự "từ".

Dưới đây là danh sách đầy đủ các ký tự "không từ", được biểu thị dưới dạng mã byte thập phân. Lưu ý - danh sách này được tổng hợp trên máy Hoa Kỳ. Tôi không biết những tác động khác mà các ngôn ngữ khác có thể có trong danh sách này.

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

Phạm vi lớp nhân vật Regex [xy]
Phạm vi lớp nhân vật không hoạt động như mong đợi. Xem câu hỏi này: Tại sao findstr không xử lý trường hợp đúng (trong một số trường hợp)? , cùng với câu trả lời này: https://stackoverflow.com/a/8767815/1012053 .

Vấn đề là FINDSTR không đối chiếu các ký tự theo giá trị mã byte của chúng (thường được coi là mã ASCII, nhưng ASCII chỉ được xác định từ 0x00 - 0x7F). Hầu hết các triển khai regex sẽ coi [AZ] là tất cả các chữ in hoa tiếng Anh. Nhưng FINDSTR sử dụng trình tự đối chiếu gần tương ứng với cách SORT hoạt động. Vì vậy, [AZ] bao gồm bảng chữ cái tiếng Anh hoàn chỉnh, cả chữ hoa và chữ thường (ngoại trừ "a"), cũng như các ký tự alpha không phải tiếng Anh có dấu phụ.

Dưới đây là danh sách đầy đủ tất cả các ký tự được FINDSTR hỗ trợ, được sắp xếp theo trình tự đối chiếu được FINDSTR sử dụng để thiết lập phạm vi lớp ký tự regex. Các ký tự được biểu diễn dưới dạng giá trị mã byte thập phân của chúng. Tôi tin rằng trình tự đối chiếu có ý nghĩa nhất nếu các ký tự được xem bằng mã trang 437. Lưu ý - danh sách này được biên dịch trên máy Hoa Kỳ. Tôi không biết những tác động khác mà các ngôn ngữ khác có thể có trong danh sách này.

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

Giới hạn thuật ngữ lớp ký tự Regex và BUG
Không chỉ FINDSTR bị giới hạn tối đa 15 thuật ngữ lớp ký tự trong một biểu thức chính quy, nó không xử lý đúng cách một nỗ lực vượt quá giới hạn. Sử dụng 16 thuật ngữ lớp ký tự trở lên dẫn đến Windows tương tác bật lên cho biết "Tiện ích Tìm chuỗi (QGREP) đã gặp sự cố và cần phải đóng. Chúng tôi xin lỗi vì sự bất tiện này." Văn bản tin nhắn thay đổi một chút tùy thuộc vào phiên bản Windows. Đây là một ví dụ về TÌM KIẾM sẽ thất bại:

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]

Lỗi này đã được báo cáo bởi người dùng DosTips Judago tại đây . Nó đã được xác nhận trên XP, Vista và Windows 7.

Tìm kiếm Regex không thành công (và có thể bị treo vô thời hạn) nếu chúng bao gồm mã byte 0xFF (thập phân 255)
Bất kỳ tìm kiếm regex nào bao gồm mã byte 0xFF (thập phân 255) sẽ không thành công. Không thành công nếu mã byte 0xFF được bao gồm trực tiếp hoặc nếu nó được bao gồm trong phạm vi lớp ký tự. Hãy nhớ rằng phạm vi lớp ký tự FINDSTR không đối chiếu các ký tự dựa trên giá trị mã byte. Nhân vật <0xFF>xuất hiện tương đối sớm trong chuỗi đối chiếu giữa <space><tab>nhân vật. Vì vậy, bất kỳ phạm vi lớp nhân vật bao gồm cả hai <space><tab>sẽ thất bại.

Hành vi chính xác thay đổi một chút tùy thuộc vào phiên bản Windows. Windows 7 bị treo vô thời hạn nếu bao gồm 0xFF. XP không bị treo, nhưng nó luôn không tìm thấy kết quả khớp và đôi khi in thông báo lỗi sau - "Quá trình đã cố ghi vào một đường ống không tồn tại."

Tôi không còn có quyền truy cập vào máy Vista, vì vậy tôi chưa thể kiểm tra trên Vista.

Lỗi Regex: .[^anySet]có thể khớp với End-Of-File
Ký tự .meta regex chỉ nên khớp với bất kỳ ký tự nào ngoài <CR>hoặc <LF>. Có một lỗi cho phép nó khớp với End-Of-File nếu dòng cuối cùng trong tệp không bị chấm dứt bởi <CR>hoặc <LF>. Tuy nhiên, .sẽ không phù hợp với một tập tin trống.

Ví dụ: một tệp có tên "test.txt" chứa một dòng duy nhất xmà không chấm dứt <CR>hoặc <LF>sẽ khớp với các mục sau:

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

Lỗi này đã được xác nhận trên XP và Win7.

Điều tương tự cũng có vẻ đúng với các bộ ký tự phủ định. Một cái gì đó giống như [^abc]sẽ phù hợp với End-Of-File. Bộ nhân vật tích cực như [abc]dường như làm việc tốt. Tôi chỉ thử nghiệm điều này trên Win7.


1
findstr cũng có lỗi khi xử lý các tệp lớn. Các tệp> 2GB có thể khiến findstr bị treo. Nó không luôn luôn xảy ra. Khi xác nhận lỗi, tôi đã tìm kiếm một tệp có dung lượng 2,3 GB không bị treo. Nó bị treo ngay cả khi chỉ tìm kiếm một tập tin duy nhất. Cách giải quyết là ống đầu ra của typethành findstr.
vỡ mộng

Có lẽ cũng đáng để đề cập đến việc findstrhỗ trợ nhiều /c:chuỗi tìm kiếm. Tôi biết câu trả lời của bạn đã chứng minh điều này. Nhưng nó là một cái gì đó không được ghi lại; và tôi đã khá ngạc nhiên khi biết về tính năng này sau khi sử dụng findstrmà không có nó trong một vài năm.
vỡ mộng

@CraigYoung - Bạn nói đúng về các nguồn chuỗi tìm kiếm. Tôi chỉnh sửa câu trả lời của tôi, cảm ơn.
dbenham

1
Khi điều tra thêm, có vẻ như một biến thể về LFvấn đề bạn đã ghi lại. Tôi nhận ra tệp thử nghiệm của mình không kết thúc LFvì tôi đã sử dụng copyở chế độ chắp thêm để tạo tệp. Tôi đã đặt một phiên dòng lệnh để chứng minh vấn đề thành câu trả lời ( stackoverflow.com/a/22943056/224704 ). Lưu ý rằng đầu vào không được chuyển hướng và tìm kiếm bị treo. Lệnh tìm kiếm chính xác tương tự không bị treo với một tệp nhỏ hơn tương tự không kết thúc LF.
vỡ mộng

1
Phát hiện mới (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 lớp ký tự) - ErrorLevel = -1073740791 (0xC0000409), cửa sổ hộp thoại báo lỗi : Find String (QGREP) Utility has stopped working; sau khi xóa một lớp hoặc hai ký tự meta ( *\.), nó hoạt động ...
aschipfl

7

findstr đôi khi bị treo bất ngờ khi tìm kiếm các tập tin lớn.

Tôi chưa xác nhận các điều kiện chính xác hoặc kích thước ranh giới. Tôi nghi ngờ bất kỳ tập tin lớn hơn 2GB có thể có nguy cơ.

Tôi đã có kinh nghiệm lẫn lộn với điều này, vì vậy nó không chỉ là kích thước tập tin. Có vẻ như đây có thể là một biến thể của FINDSTR bị treo trên XP và Windows 7 nếu đầu vào được chuyển hướng không kết thúc với LF , nhưng như đã chứng minh vấn đề cụ thể này biểu hiện khi đầu vào không được chuyển hướng.

Phiên dòng lệnh sau (Windows 7) trình bày cách findstrcó thể treo khi tìm kiếm tệp 3 GB.

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>

Lưu ý, tôi đã xác minh trong trình chỉnh sửa hex rằng tất cả các dòng được kết thúc bằng CRLF. Điều bất thường duy nhất là tập tin bị chấm dứt 0x1Ado cách copylàm việc . Tuy nhiên, lưu ý rằng sự bất thường này không gây ra sự cố trên các tệp "nhỏ" .

Với thử nghiệm bổ sung tôi đã xác nhận như sau:

  • Sử dụng copyvới /btùy chọn cho các tệp nhị phân sẽ ngăn việc thêm 0x1Aký tự và findstrkhông bị treo trên tệp 3 GB.
  • Việc chấm dứt tệp 3GB bằng một ký tự khác cũng gây ra lỗi findstrtreo.
  • 0x1Atự không gây ra bất kỳ vấn đề nào trên tệp "nhỏ". (Tương tự cho các ký tự kết thúc khác.)
  • Thêm CRLFsau khi 0x1Agiải quyết vấn đề. ( LFtự nó có lẽ sẽ đủ.)
  • Sử dụng typeđể ống các tập tin vào findstrcông trình mà không treo. (Điều này có thể là do tác dụng phụ của một trong hai typehoặc |chèn thêm End Of Line.)
  • Sử dụng đầu vào chuyển hướng <cũng gây rafindstr treo. Nhưng điều này được mong đợi; như được giải thích trong bài của dbenham : "đầu vào được chuyển hướng phải kết thúc bằng LF" .

1
+1, tôi có thể xác nhận sự cố trên máy Win7 của mình. Một tệp có kích thước chính xác 2GiB được treo khi ký tự cuối cùng không có <LF>. Một tập tin hai byte nhỏ hơn không treo. Rất khó chịu!
dbenham

6

Khi một số lệnh được đặt trong dấu ngoặc đơn và có các tệp được chuyển hướng đến toàn bộ khối:

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

... sau đó các tệp vẫn mở miễn là các lệnh trong khối được kích hoạt, vì vậy các lệnh có thể di chuyển con trỏ tệp của các tệp được chuyển hướng. Cả hai lệnh THÊM và TÌM di chuyển con trỏ tệp Stdin đến đầu tệp trước khi xử lý tệp, do đó, cùng một tệp có thể được xử lý nhiều lần trong khối. Ví dụ: mã này:

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

... tạo ra kết quả tương tự như kết quả này:

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

Mã này:

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

... tạo ra kết quả tương tự như kết quả này:

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

TÌM KIẾM là khác nhau; nó không di chuyển con trỏ tệp Stdin từ vị trí hiện tại của nó. Ví dụ: mã này chèn một dòng mới sau một dòng tìm kiếm:

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

Chúng tôi có thể sử dụng tốt tính năng này với sự trợ giúp của một chương trình phụ trợ cho phép chúng tôi di chuyển con trỏ tệp của tệp được chuyển hướng, như trong ví dụ này .

Hành vi này đã được báo cáo đầu tiên bởi jeb tại bài viết này .


EDIT 2018-08-18 : Đã báo cáo lỗi FINDSTR mới

Lệnh FINDSTR có một lỗi lạ xảy ra khi lệnh này được sử dụng để hiển thị các ký tự có màu VÀ đầu ra của lệnh đó được chuyển hướng đến thiết bị CON. Để biết chi tiết về cách sử dụng lệnh FINDSTR để hiển thị văn bản màu, xem chủ đề này .

Khi đầu ra của dạng lệnh FINDSTR này được chuyển hướng đến CON, một điều kỳ lạ xảy ra sau khi văn bản được xuất ra theo màu mong muốn: tất cả văn bản sau khi nó được xuất thành ký tự "vô hình", mặc dù mô tả chính xác hơn là văn bản đó đầu ra dưới dạng văn bản màu đen trên nền đen. Văn bản gốc sẽ xuất hiện nếu bạn sử dụng lệnh MÀU để đặt lại màu nền trước và màu nền của toàn bộ màn hình. Tuy nhiên, khi văn bản "vô hình", chúng tôi có thể thực thi lệnh SET / P, vì vậy tất cả các ký tự được nhập sẽ không xuất hiện trên màn hình. Hành vi này có thể được sử dụng để nhập mật khẩu.

@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%"

2

Tôi muốn báo cáo một lỗi liên quan đến phần Nguồn dữ liệu để tìm kiếm trong câu trả lời đầu tiên khi sử dụng en dash (-) hoặc em dash (-) trong tên tệp.

Cụ thể hơn, nếu bạn chuẩn bị sử dụng tùy chọn đầu tiên - tên tệp được chỉ định làm đối số , tệp sẽ không được tìm thấy. Ngay khi bạn sử dụng tùy chọn 2 - stdin thông qua chuyển hướng hoặc luồng dữ liệu 3 từ một đường ống , findstr sẽ tìm thấy tệp.

Ví dụ: tập lệnh bó đơn giản này:

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

sẽ in:

Tên tệp với dấu gạch ngang:

  1. Là đối số
    FINDSTR: Không thể mở tên tệp bằng - dash.txt

  2. Như stdin thông qua chuyển hướng,
    tôi là tập tin với một dấu gạch ngang.

  3. Như luồng dữ liệu từ một đường ống
    Tôi là tệp có dấu gạch ngang.

Tên tệp với dấu gạch ngang em:

  1. Là đối số
    FINDSTR: Không thể mở tên tệp bằng - dash.txt

  2. Như stdin thông qua chuyển hướng,
    tôi là tập tin với một dấu gạch ngang.

  3. Như luồng dữ liệu từ một đường ống,
    tôi là tệp có dấu gạch ngang.

Hy vọng nó giúp.

M ..


1
Xin chào matro, trong khi ý kiến ​​của bạn có thể đúng, tôi không chắc họ không giải quyết câu hỏi thực tế.
Wai Ha Lee

Tôi tin rằng đây là một vấn đề unicode, mà FINDSTR không hỗ trợ. Chuyển hướng CMD.EXE có thể mở đúng tên tệp bằng unicode, cũng như lệnh TYPE. Nhưng ở đâu đó dọc theo dòng, FINDSTR chuyển đổi cả en-dash và em-dash thành một dấu gạch ngang bình thường và tất nhiên HĐH không thể tìm thấy tên đó. Nếu bạn tạo một tệp khác thay thế dấu gạch ngang cho en-dash và / hoặc em-dash, thì FINDSTR sẽ tìm kiếm tệp dash nếu được cung cấp một tên có chứa en-dash hoặc em-dash.
dbenham 22/03/2015

Tôi sẽ phân loại vấn đề này là một hạn chế chứ không phải là một lỗi.
dbenham 22/03/2015

Trên thực tế, đây không phải là một vấn đề unicode vì nó được mở rộng ASCII. Tôi đã ghi lại vấn đề này trong câu trả lời ban đầu của mình dưới tiêu đề Ký tự giới hạn cho các tham số dòng lệnh - Chuyển đổi ASCII mở rộng . FINDSTR biến đổi một số mã ASCII mở rộng thành ASCII thực sự "có liên quan", bao gồm en-dash và em-dash.
dbenham

1

Các findstrlệnh đặt ErrorLevel(hoặc mã exit) đến một trong các giá trị sau, cho rằng không có công tắc không hợp lệ hoặc không tương thích và không có chuỗi tìm kiếm vượt quá giới hạn độ dài áp dụng:

  • 0 khi ít nhất một trận đấu duy nhất gặp phải trong một dòng trong tất cả các tệp được chỉ định;
  • 1 nếu không thì;

Một dòng được coi là có chứa một trận đấu khi:

  • không có /Vtùy chọn nào được đưa ra và biểu thức tìm kiếm xảy ra ít nhất một lần;
  • các /Vtùy chọn được đưa ra và biểu thức tìm kiếm không xảy ra;

Điều này có nghĩa là /Vtùy chọn cũng thay đổi trả lại ErrorLevel, nhưng nó không chỉ hoàn nguyên nó!

Ví dụ, khi bạn đã có một tập tin test.txtvới hai dòng, một trong số đó có chứa chuỗi textnhưng một trong những khác không, cả hai findstr "text" "test.txt"findstr /V "text" "test.txt"trả về một ErrorLevelsố 0.

Về cơ bản bạn có thể nói: nếu findstrtrả về ít nhất một dòng, ErrorLevelđược đặt thành 0, khác với 1.

Lưu ý rằng /Mtùy chọn không ảnh hưởng đến ErrorLevelgiá trị, nó chỉ làm thay đổi đầu ra.

(Chỉ vì mục đích hoàn chỉnh: findlệnh hoạt động chính xác theo cùng một cách đối với /Vtùy chọn và ErrorLevel; /Ctùy chọn không ảnh hưởng ErrorLevel.)


1

FINDSTR có một lỗi màu mà tôi đã mô tả và giải quyết tại /superuser/1535310/is-there-a-better-way-to-mitigate-this-obscure-color-orms-when-piping-to -findstr / 1538802? noredirect = 1 # bình luận2339443_1538802

Để tóm tắt luồng đó, lỗi là nếu đầu vào được dẫn đến FINDSTR trong một khối mã được ngoặc đơn, mã màu thoát ANSI nội tuyến sẽ ngừng hoạt động trong các lệnh được thực hiện sau đó. Một ví dụ về mã màu nội tuyến là: echo %magenta%Alert: Something bad happened%yellow%(trong đó màu đỏ tươi và màu vàng là các vars được xác định trước đó trong tệp .bat là mã màu thoát ANSI tương ứng).

Giải pháp ban đầu của tôi là gọi một chương trình con không làm gì sau TÌM KIẾM. Bằng cách nào đó, cuộc gọi hoặc trả lại "đặt lại" bất cứ điều gì cần được đặt lại.

Sau đó, tôi phát hiện ra một giải pháp khác có lẽ hiệu quả hơn: đặt cụm từ FINDSTR trong ngoặc đơn, như trong ví dụ sau: echo success | ( FINDSTR /R success ) Đặt cụm từ FINDSTR trong một khối mã lồng nhau xuất hiện để cô lập lỗi mã màu của FINDSTR để nó không ảnh hưởng đến những gì bên ngoài lồng nhau khối. Có lẽ kỹ thuật này cũng sẽ giải quyết được một số tác dụng phụ FINDSTR không mong muốn khác .


Tuyệt vời tìm thấy. Nhưng các quy tắc của bạn có thể được đơn giản hóa (ít nhất là trên máy Windows 10 doanh nghiệp của tôi). FINDSTR ngăn tất cả các chuỗi thoát giao diện điều khiển hoạt động cho các lệnh tiếp theo trong cùng một khối lệnh. Sẽ không có vấn đề gì nếu FINDSTR đọc một đường ống, đầu vào được chuyển hướng hoặc một tệp. Lỗi chuỗi thoát không bị hạn chế đối với mã màu. Khối lệnh là bất kỳ nhóm lệnh nào trong ngoặc đơn và / hoặc các lệnh được nối thông qua &, && hoặc ||
dbenham

@dbenham: Tổng quát hóa tốt đẹp của vấn đề. Bạn có biết liệu giải pháp của tôi - lồng cụm từ FINDSTR bên trong dấu ngoặc đơn - cũng hoạt động trong trường hợp chung không? Và bạn có biết liệu giải pháp của tôi có bất kỳ tác dụng phụ không mong muốn?
Dolores Stevens

Tôi đã không thực hiện bất kỳ thử nghiệm toàn diện nào, nhưng vâng, các dấu ngoặc đơn lồng nhau dường như là một giải pháp chung và tôi không thể nghĩ ra bất kỳ tác dụng phụ không mong muốn nào có thể xảy ra.
dbenham

-1

/ D mẹo cho nhiều thư mục: đặt danh sách thư mục của bạn trước chuỗi tìm kiếm. Tất cả đều hoạt động:

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

Như mong đợi, đường dẫn có liên quan đến vị trí nếu bạn không bắt đầu các thư mục \. Bao quanh đường dẫn "là tùy chọn nếu không có khoảng trắng trong tên thư mục. Kết thúc \là tùy chọn. Đầu ra của vị trí sẽ bao gồm bất kỳ con đường nào bạn cung cấp cho nó. Nó sẽ làm việc có hoặc không có xung quanh danh sách thư mục với ".


Tôi không thấy bất cứ điều gì không có giấy tờ ở đây. Tùy chọn / D được mô tả trong phần trợ giúp tích hợp. Đây không phải là một câu hỏi cho lời khuyên chung về cách sử dụng FINDSTR. Nó được dự định nghiêm ngặt để liệt kê các tính năng, hạn chế và / hoặc lỗi không có giấy tờ.
dbenham

1
@dbenham đúng là nó không thực sự không có giấy tờ, nhưng tôi thấy tôi phải tinh ranh với findstr để có được kết quả tôi muốn và đang chia sẻ những gì tôi thấy DID hoạt động để mọi người không lãng phí thời gian thử nghiệm các lệnh KHÔNG hoạt động. hth (Tôi buồn vì bạn không thích dữ liệu đầu vào của tôi - nó chỉ nhằm mục đích mang tính xây dựng)
gordon

IMHO công tắc / D được mô tả rõ ràng trong phần trợ giúp tích hợp: /D:dirlist Search a semicolon-delimited list of directoriesvà nó được đặt trước chuỗi tìm kiếm, vì vậy tôi không hiểu chính xác những gì "bạn đã tìm thấy" về công tắc / D (và các lệnh "đó là gì" KHÔNG làm việc ") ...
Aacini

@Aacini trong nhiều ngôn ngữ, thứ tự các thuộc tính không quan trọng. Tôi hiểu tài liệu cho findstrdanh sách / D đầu tiên. Có, tôi không có tranh luận với tính năng được ghi lại, nó chỉ không được ghi lại về gotcha mà thứ tự của các thuộc tính quan trọng. Tôi làm rất ít công việc dòng lệnh, vì vậy khi tôi đang điều khiển một lệnh, không nhận thấy thứ tự tạo ra sự khác biệt, tôi chỉ thêm các thuộc tính khi tôi nhận được chúng (và theo thứ tự chữ cái, C có trước D). Tôi đã thực sự thất vọng và đã chia sẻ kinh nghiệm "tìm thấy" của mình cho bất kỳ ai khác không làm việc nhiều với dòng lệnh.
gordon

1
Thứ tự của các thuộc tính tùy chọn thường không quan trọng. Các findstrtài liệu xác định rằng stringsmột phần là KHÔNG bắt buộc và rằng bạn phải đặt nó sau khi tùy chọn thuộc tính và trước khi tùy chọn danh sách tên tập tin. Nếu "bạn tìm thấy" là việc sử dụng một lệnh mà không tuân theo định dạng sử dụng của nó gây ra lỗi, thì một điểm như vậy cũng được ghi lại. Xem Cú pháp lệnh : "Cú pháp xuất hiện theo thứ tự bạn phải nhập lệnh và bất kỳ tham số nào tuân theo lệnh đó"
Aacini
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.