Jakie są nieudokumentowane funkcje i ograniczenia polecenia Windows FINDSTR?

188

Polecenie FINDSTR w systemie Windows jest strasznie udokumentowane. Dostępna jest bardzo prosta pomoc z wiersza poleceń FINDSTR /?, lub HELP FINDSTR, ale jest ona wyjątkowo nieodpowiednia. Jest trochę więcej dokumentacji online na https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/findstr .

Istnieje wiele funkcji i ograniczeń FINDSTR, o których nawet nie wspomina się w dokumentacji. Nie można ich również przewidzieć bez wcześniejszej wiedzy i / lub starannych eksperymentów.

Pytanie brzmi: jakie są nieudokumentowane funkcje i ograniczenia FINDSTR?

Celem tego pytania jest zapewnienie kompleksowego repozytorium wielu nieudokumentowanych funkcji, aby:

A) Programiści mogą w pełni korzystać z dostępnych tam funkcji.

B) Deweloperzy nie marnują czasu na zastanawianie się, dlaczego coś nie działa, gdy wydaje się, że powinno.

Przed udzieleniem odpowiedzi upewnij się, że znasz istniejącą dokumentację. Jeśli informacje są objęte pomocą, to nie należy tutaj.

Nie jest to również miejsce do pokazania interesujących zastosowań FINDSTR. Jeśli osoba logiczna mogłaby przewidzieć zachowanie określonego użycia FINDSTR na podstawie dokumentacji, nie należy tutaj.

W ten sam sposób, jeśli osoba logiczna mogłaby przewidzieć zachowanie określonego użycia na podstawie informacji zawartych w jakichkolwiek istniejących odpowiedziach, to znowu nie należy tutaj.

dbenham
źródło
15
Lub, alternatywnie, możesz porzucić gówniane, nieudokumentowane narzędzie MS i zainstalować / używać, grepco jest bardzo dobrze zrozumiane i udokumentowane :-) Zobacz na przykład stackoverflow.com/questions/2635740/… .
paxdiablo
17
Oczywiście, jeśli jesteś w stanie użyć czegoś innego niż FINDSTR, jest to wysoce zalecane. Ale niektóre osoby znajdują się w środowiskach, w których narzędzia innych firm są zabronione.
dbenham
4
Bez przestępstwa. Poważnie zastanawiałem się nad umieszczeniem własnego zrzeczenia się odpowiedzialności FINDSTR, które było podobne do twojego komentarza! :)
dbenham
41
Jestem zszokowany i rozczarowany, że ktoś uzna to pytanie za „niekonstruktywne” i zagłosuje za jego zamknięciem. Wiele zastanawiano się nad tym pytaniem, aby uniknąć „opinii, debaty, argumentów, ankiet lub rozszerzonej dyskusji”. Pytanie zostało opublikowane przez 3,5 miesiąca i nie wystąpił żaden z cytowanych negatywów. Sparowana odpowiedź jest pełna faktów i wymagała wielu godzin żmudnych badań i eksperymentów.
dbenham
6
Niektórzy czytelnicy mogą być zainteresowani historycznym kontekstem polecenia findstr: blogs.msdn.com/b/oldnewthing/archive/2012/11/28/10372436.aspx
Harry Johnston

Odpowiedzi:

279

Przedmowa
Wiele informacji zawartych w tej odpowiedzi zostało zebranych na podstawie eksperymentów przeprowadzonych na komputerze z systemem Vista. O ile wyraźnie nie zaznaczono inaczej, nie potwierdziłem, czy informacje dotyczą innych wersji systemu Windows.

Dane wyjściowe FINDSTR
Dokumentacja nigdy nie zadaje sobie trudu, aby wyjaśnić dane wyjściowe FINDSTR. Wskazuje to na to, że drukowane są pasujące linie, ale nic więcej.

Format dopasowanego wyjścia liniowego jest następujący:

filename: lineNumber: lineOffset: text

gdzie

fileName: = nazwa pliku zawierającego pasującą linię. Nazwa pliku nie jest drukowana, jeśli żądanie dotyczyło jednoznacznie pojedynczego pliku lub podczas wyszukiwania danych wejściowych w trybie potokowym lub danych przekierowanych. Po wydrukowaniu nazwa pliku zawsze będzie zawierać wszelkie podane informacje o ścieżce. Dodatkowe informacje o ścieżce zostaną dodane, jeśli/Szostanie użyta opcja. Ścieżka drukowana jest zawsze względna do podanej ścieżki lub względna do bieżącego katalogu, jeśli nie została podana.

Uwaga - Podczas wyszukiwania wielu plików można uniknąć prefiksu nazwy pliku, używając niestandardowych (i słabo udokumentowanych) symboli wieloznacznych < i >. Dokładne zasady działania tych symboli wieloznacznych można znaleźć tutaj . Na koniec możesz spojrzeć na ten przykład, w jaki sposób niestandardowe symbole wieloznaczne działają z FINDSTR .

lineNumber: = Numer linii pasującego wiersza reprezentowany jako wartość dziesiętna, gdzie 1 oznacza pierwszy wiersz danych wejściowych. Drukowane tylko, jeśli/Npodano opcję.

lineOffset: = Przesunięcie dziesiętnego bajtu na początku pasującej linii, przy czym 0 oznacza 1. znak 1. linii. Drukowane tylko, jeśli/Opodano opcję. To nie jestprzesunięcie dopasowania w linii. Jest to liczba bajtów od początku pliku do początku linii.

text = Binarna reprezentacja pasującej linii, łącznie z dowolnymi <CR> i / lub <LF>. Nic nie pozostaje poza wyjściem binarnym, tak że ten przykład, który pasuje do wszystkich wierszy, utworzy dokładną kopię binarną oryginalnego pliku.

FINDSTR "^" FILE >FILE_COPY

Opcja / A ustawia kolor fileName :, lineNumber :, i lineOffset: tylko dane wyjściowe. Tekst pasującej linii jest zawsze wyprowadzany z bieżącym kolorem konsoli. Opcja / A działa tylko wtedy, gdy dane wyjściowe są wyświetlane bezpośrednio na konsoli. Opcja / A nie ma wpływu, jeśli dane wyjściowe zostaną przekierowane do pliku lub potoku. Zobacz edycję 2018-08-18 w odpowiedzi Aacini, aby uzyskać opis błędnego zachowania po przekierowaniu danych wyjściowych do CON.

Większość znaków kontrolnych i wiele rozszerzonych znaków ASCII jest wyświetlanych jako kropki na XP.
FINDSTR na XP wyświetla większość niedrukowalnych znaków kontrolnych z pasujących linii jako kropki (kropki) na ekranie. Następujące znaki kontrolne są wyjątkami; wyświetlają się one same: 0x09 Tab, 0x0A LineFeed, 0x0B Tab pionowy, 0x0C Form Feed, 0x0D Powóz powrotny.

XP FINDSTR przekształca również wiele rozszerzonych znaków ASCII w kropki. Rozszerzone znaki ASCII wyświetlane w XP jako kropki są takie same, jak znaki przekształcane po dostarczeniu z wiersza poleceń. Zobacz sekcję „Limity znaków dla parametrów wiersza poleceń - Rozszerzona transformacja ASCII” , w dalszej części tego postu

Znaki kontrolne i rozszerzone ASCII nie są konwertowane na kropki w XP, jeśli dane wyjściowe są przesyłane potokowo, przekierowywane do pliku lub w ramach klauzuli FOR IN ().

Vista i Windows 7 zawsze wyświetlają wszystkie znaki jako siebie, nigdy jako kropki.

Kody zwrotne (ERRORLEVEL)

  • 0 (sukces)
    • Znaleziono dopasowanie w co najmniej jednej linii co najmniej jednego pliku.
  • 1 (awaria)
    • Nie znaleziono dopasowania w żadnym wierszu żadnego pliku.
    • Nieprawidłowy kolor określony przez /A:xxopcję
  • 2 (błąd)
    • Niezgodne opcje /Li /Roba określone
    • Brakuje argumentu po /A:, /F:, /C:, /D:, lub/G:
    • Plik określony przez /F:filelub /G:filenie został znaleziony
  • 255 (błąd)

Źródło danych do wyszukiwania (zaktualizowane na podstawie testów w systemie Windows 7)
Findstr może wyszukiwać dane tylko z jednego z następujących źródeł:

  • nazwy plików określone jako argumenty i / lub za pomocą /F:fileopcji.

  • standardowe poprzez przekierowanie findstr "searchString" <file

  • strumień danych z potoku type file | findstr "searchString"

Argumenty / opcje mają pierwszeństwo przed przekierowaniem, które ma pierwszeństwo przed przesyłanymi danymi.

Argumenty nazwy pliku i /F:filemożna je łączyć. Można użyć wielu argumentów nazwy pliku. Jeśli /F:filepodano wiele opcji, używana jest tylko ostatnia. Symbole wieloznaczne są dozwolone w argumentach nazw plików, ale nie w obrębie pliku wskazywanego przez /F:file.

Źródło ciągów wyszukiwania (zaktualizowane na podstawie testów z Windows 7) i opcje mogą być łączone. Można podać wiele opcji. Jeśli podano wiele opcji, używana jest tylko ostatnia. Jeśli użyty jest albo lub, zakłada się, że wszystkie argumenty nie będące opcjami są plikami do przeszukania. Jeśli ani nie zostanie użyty, ani pierwszy argument nie będący opcją jest traktowany jako lista rozdzielonych spacjami haseł.
/G:file/C:string/C:string/G:file/G:file/C:string/G:file/C:string

Podczas korzystania z /F:FILEopcji nazwy plików nie mogą być cytowane w pliku .
Nazwy plików mogą zawierać spacje i inne znaki specjalne. Większość poleceń wymaga cytowania takich nazw plików. Ale /F:files.txtopcja FINDSTR wymaga, aby nazwy plików w plikach.txt NIE były cytowane. Plik nie zostanie znaleziony, jeśli nazwa zostanie podana.

BŁĄD - Krótkie nazwy plików 8.3 mogą/D/S
uszkodzić opcje i Podobnie jak w przypadku wszystkich poleceń systemu Windows, FINDSTR będzie próbował dopasować zarówno długą nazwę, jak i krótką nazwę 8.3, podczas wyszukiwania plików do przeszukania. Załóżmy, że bieżący folder zawiera następujące niepuste pliki:

b1.txt
b.txt2
c.txt

Następujące polecenie z powodzeniem znajdzie wszystkie 3 pliki:

findstr /m "^" *.txt

b.txt2pasuje, ponieważ odpowiada odpowiednia krótka nazwa B9F64~1.TXT. Jest to zgodne z zachowaniem wszystkich innych poleceń systemu Windows.

Ale błąd w opcjach /Di /Spowoduje, że następujące polecenia znajdują się tylkob1.txt

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

Błąd uniemożliwia b.txt2odnalezienie, a także wszystkich nazw plików posortowanych po b.txt2tym samym katalogu. a.txtZnaleziono dodatkowe pliki, które sortują się wcześniej . Dodatkowe pliki, które sortują później, na przykład d.txt, są pomijane po uruchomieniu błędu.

Każdy przeszukiwany katalog jest traktowany niezależnie. Na przykład /Sopcja z powodzeniem rozpocznie wyszukiwanie w folderze podrzędnym po nieudanym znalezieniu plików w elemencie nadrzędnym, ale gdy błąd spowoduje pominięcie krótkiej nazwy pliku w elemencie podrzędnym, wówczas wszystkie kolejne pliki w tym folderze podrzędnym również zostaną pominięte .

Polecenia działają bezbłędnie, jeśli te same nazwy plików są tworzone na komputerze z wyłączonym generowaniem nazw NTFS 8.3. Oczywiście b.txt2nie zostałby znaleziony, ale c.txtzostałby znaleziony poprawnie.

Nie wszystkie krótkie nazwy powodują błąd. Wszystkie zaobserwowane przeze mnie przypadki błędnego zachowania dotyczą rozszerzenia dłuższego niż 3 znaki o krótkiej nazwie 8.3, która zaczyna się tak samo jak normalna nazwa, która nie wymaga nazwy 8.3.

Błąd został potwierdzony w systemach XP, Vista i Windows 7.

Znaków Niedrukowalny oraz /Popcja opcja powoduje FINDSTR pominąć dowolny plik, który zawiera jeden z następujących kodów bajtowych dziesiętnych: 0-7, 14-25, 27-31.
/P

Innymi słowy, /Popcja pomija tylko pliki zawierające niedrukowalne znaki kontrolne. Znaki kontrolne to kody mniejsze lub równe 31 (0x1F). FINDSTR traktuje następujące znaki kontrolne jako drukowalne:

 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)

Wszystkie pozostałe znaki sterujące są traktowane jako niedrukowalne, których obecność powoduje, że /Popcja pomija plik.

Dołączone dane wejściowe potokowe i przekierowane mogły zostać <CR><LF>dołączone.
Jeśli dane wejściowe są przesyłane strumieniowo <LF>, a ostatni znak strumienia nie jest , funkcja FINDSTR automatycznie dołącza <CR><LF>się do danych wejściowych. Zostało to potwierdzone w systemach XP, Vista i Windows 7. (Kiedyś myślałem, że potok Windows był odpowiedzialny za modyfikację danych wejściowych, ale od tego czasu odkryłem, że FINDSTR faktycznie dokonuje modyfikacji).

To samo dotyczy przekierowanych danych wejściowych w systemie Vista. Jeśli ostatnim znakiem pliku używanego jako przekierowane dane wejściowe nie jest <LF>, wówczas FINDSTR automatycznie dołącza <CR><LF>się do danych wejściowych. Jednak XP i Windows 7 nie zmieniają przekierowanych danych wejściowych.

Findstr wisi na XP i Windows 7, jeśli przekierowany wejście nie kończy<LF>
To jest paskudne „cecha” na XP i Windows 7. Jeśli ostatni znak pliku używany jako wejście przekierowanego nie kończy się <LF>, a następnie FINDSTR zawiśnie w nieskończoność po nim osiąga koniec przekierowanego pliku.

Ostatni wiersz danych przesyłanych strumieniowo można zignorować, jeśli składa się z pojedynczego znaku.
Jeśli wejście jest przesyłane <LF>strumieniowo, a ostatni wiersz składa się z pojedynczego znaku, po którym nie następuje , funkcja FINDSTR całkowicie ignoruje ostatni wiersz.

Przykład - Pierwsze polecenie z pojedynczym znakiem i bez niego <LF>nie pasuje, ale drugie polecenie z 2 znakami działa dobrze, podobnie jak trzecie polecenie, które ma jeden znak z zakończeniem nowej linii.

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

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

> echo x| findstr "^"
x

Zgłoszony przez użytkownika DosTips Sponge Belly przy nowym błędzie findstr . Potwierdzono w XP, Windows 7 i Windows 8. Nie słyszałem jeszcze o Vistie. (Nie mam już Visty do przetestowania).

Składnia opcji
Opcje mogą być poprzedzone jednym z nich /lub - Opcje mogą być łączone po jednym /lub -. Jednak połączona lista opcji może zawierać co najwyżej jedną opcję wieloznakową, taką jak WYŁ. Lub F :, a opcja wieloznakowa musi być ostatnią opcją na liście.

Poniżej podano wszystkie równoważne sposoby wyrażenia wyrażenia regularnego bez rozróżniania wielkości liter dla dowolnego wiersza zawierającego zarówno „cześć”, jak i „do widzenia” w dowolnej kolejności

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

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

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

Limity długości ciągu wyszukiwania
W systemie Vista maksymalna dozwolona długość pojedynczego ciągu wyszukiwania wynosi 511 bajtów. Jeśli dowolny szukany ciąg przekracza 511, wynikiem jest FINDSTR: Search string too long.błąd z ERRORLEVEL 2.

Podczas wyszukiwania wyrażeń regularnych maksymalna długość szukanego ciągu wynosi 254. Wyrażenie regularne o długości od 255 do 511 spowoduje FINDSTR: Out of memorybłąd z ERRORLEVEL 2. Błąd wyrażenia regularnego> 511 spowoduje FINDSTR: Search string too long.błąd.

W systemie Windows XP długość ciągu wyszukiwania jest najwyraźniej krótsza. Błąd Findstr: „Ciąg wyszukiwania zbyt długi”: Jak wyodrębnić i dopasować podciąg w pętli „for”? Limit XP wynosi 127 bajtów dla wyszukiwania dosłownego i wyrażenia regularnego.

Limity długości linii
Pliki określone jako argument wiersza poleceń lub za pomocą opcji / F: FILE nie mają znanego limitu długości linii. Pomyślnie uruchomiono wyszukiwanie dla pliku 128 MB, który nie zawierał ani jednego <LF>.

Dane przesyłane potokowo i przekierowane dane wejściowe są ograniczone do 8191 bajtów na linię. Ten limit jest „funkcją” FINDSTR. Nie jest związany z potokami ani przekierowaniami. FINDSTR przy użyciu przekierowanego wejścia stdin lub potokowego nigdy nie będzie pasował do żadnej linii, która ma> 8k bajtów. Linie> = 8k generują komunikat o błędzie do stderr, ale ERRORLEVEL wciąż wynosi 0, jeśli szukany ciąg znajduje się w co najmniej jednym wierszu co najmniej jednego pliku.

Domyślny typ wyszukiwania:
/C:"string" dosłowny vs. wyrażenie regularne - domyślnie jest to literał / L. Jawne połączenie opcji / L z / C: „string” z pewnością działa, ale jest redundantne.

"string argument"- Wartość domyślna zależy od zawartości pierwszego szukanego ciągu. (Pamiętaj, że <spacja> jest używana do rozdzielenia ciągów wyszukiwania.) Jeśli pierwszy ciąg wyszukiwania jest prawidłowym wyrażeniem regularnym zawierającym co najmniej jeden nieoznakowany metaznak, wówczas wszystkie ciągi wyszukiwania są traktowane jako wyrażenia regularne. W przeciwnym razie wszystkie ciągi wyszukiwania są traktowane jak literały. Na przykład "51.4 200"będą traktowane jako dwa wyrażenia regularne, ponieważ pierwszy ciąg zawiera kropkę bez znaku ucieczki, podczas gdy "200 51.4"będzie traktowany jako dwa literały, ponieważ pierwszy ciąg nie zawiera żadnych metaznaków.

/G:file- Wartość domyślna zależy od zawartości pierwszego niepustego wiersza w pliku. Jeśli pierwszy ciąg wyszukiwania jest prawidłowym wyrażeniem regularnym zawierającym co najmniej jeden nieoznakowany metaznak, wówczas wszystkie ciągi wyszukiwania są traktowane jako wyrażenia regularne. W przeciwnym razie wszystkie ciągi wyszukiwania są traktowane jak literały.

Zalecenie - Zawsze używaj /Lopcji dosłownie lub /Ropcji wyrażenia regularnego, gdy używasz "string argument"lub /G:file.

BŁĄD - Podanie wielu dosłownych ciągów wyszukiwania może dać nierzetelne wyniki

Poniższy prosty przykład FINDSTR nie może znaleźć dopasowania, chociaż powinno.

echo ffffaaa|findstr /l "ffffaaa faffaffddd"

Ten błąd został potwierdzony w systemach Windows Server 2003, Windows XP, Vista i Windows 7.

Na podstawie eksperymentów FINDSTR może się nie powieść, jeśli zostaną spełnione wszystkie następujące warunki:

  • Wyszukiwanie wykorzystuje wiele literalnych ciągów wyszukiwania
  • Ciągi wyszukiwania mają różne długości
  • Krótki ciąg wyszukiwania ma pewne nakładanie się z dłuższym ciągiem wyszukiwania
  • W wyszukiwaniu rozróżniana jest wielkość liter (brak /Iopcji)

W każdej porażce, którą widziałem, zawsze zawodzi jeden z krótszych ciągów wyszukiwania.

Aby uzyskać więcej informacji, zobacz Dlaczego ten przykład FINDSTR z wieloma dosłownymi ciągami wyszukiwania nie znajduje dopasowania?

Cudzysłowy i odstępy w argumentach wiersza poleceń
Uwaga - Komentarze użytkownika MC ND odzwierciedlają naprawdę przerażająco skomplikowane reguły dla tej sekcji. W grę wchodzą 3 odrębne fazy analizy:

  • Pierwszy cmd.exe może wymagać zmiany cudzysłowów na ^ ”(naprawdę nie ma to nic wspólnego z FINDSTR)
  • Następnie FINDSTR używa analizatora składni argumentów MS C / C ++ sprzed 2008 roku , który ma specjalne reguły dla „i \
  • Po zakończeniu parsera argumentów FINDSTR dodatkowo traktuje \, po którym następuje znak alfanumeryczny, jako dosłowny, ale \ po którym następuje znak inny niż alfanumeryczny, jako znak zmiany znaczenia

Pozostała część tej podświetlonej sekcji nie jest w 100% poprawna. Może służyć jako przewodnik w wielu sytuacjach, ale powyższe zasady są wymagane do pełnego zrozumienia.

Escaping Cytat w ciągach wyszukiwania wiersza poleceń
Cytaty w ciągach wyszukiwania wiersza poleceń muszą być poprzedzane odwrotnym ukośnikiem \". Dotyczy to zarówno literalnych, jak i wyrażeń regularnych. Informacje te zostały potwierdzone w systemach XP, Vista i Windows 7.

Uwaga: cytat może również wymagać zmiany znaczenia dla analizatora składni CMD.EXE, ale nie ma to nic wspólnego z FINDSTR. Na przykład, aby wyszukać pojedynczy cytat, możesz użyć:

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

Cofanie ukośnika
odwrotnego w dosłownym ciągu wyszukiwania w wierszu poleceń Odwrotny ukośnik w dosłownym ciągu wyszukiwania można zwykle przedstawić jako \lub jako \\. Zazwyczaj są one równoważne. (Mogą występować nietypowe przypadki w Vistie, w których odwrotny ukośnik zawsze musi być poprzedzony, ale nie mam już komputera z Vista do przetestowania) .

Ale są pewne szczególne przypadki:

Podczas wyszukiwania kolejnych ukośników odwrotnych wszystkie oprócz ostatniego muszą być poprzedzone znakiem ucieczki. Ostatniego ukośnika odwrotnego można opcjonalnie usunąć.

  • \\może być kodowany jako \\\lub\\\\
  • \\\może być kodowany jako \\\\\lub\\\\\\

Wyszukiwanie jednego lub więcej ukośników odwrotnych przed wyceną jest dziwne. Logika sugerowałaby, że cytat musi zostać pominięty, a każdy z wiodących ukośników odwrotnych musiałby zostać usunięty, ale to nie działa! Zamiast tego każdy z wiodących odwrotnych ukośników musi być podwójnie zmieniony, a cytat jest normalnie zmieniany:

  • \" musi być zakodowany jako \\\\\"
  • \\" musi być zakodowany jako \\\\\\\\\"

Jak wcześniej wspomniano, jeden lub więcej cytatów ze znakiem ucieczki może również wymagać zmiany znaczenia ^dla analizatora składni CMD

Informacje w tej sekcji zostały potwierdzone na XP i Windows 7.

Cofanie odwrotnego ukośnika w ciągach wyszukiwania wyrażeń regularnych w wierszu polecenia

  • Tylko Vista: ukośnik odwrotny w wyrażeniu regularnym musi być albo podwójnym klawiszem Esc \\\\, albo pojedynczym klawiszem Esc w zestawie klas znaków, takim jak [\\]

  • XP i Windows 7: Ukośnik odwrotny w wyrażeniu regularnym zawsze można przedstawić jako [\\]. Zwykle może być reprezentowany jako \\. Ale to nigdy nie działa, jeśli odwrotny ukośnik poprzedza cytowany znak.

    Jeden lub więcej odwrotnych ukośników przed cytowanym znakiem musi być albo podwójnym znakiem ucieczki, albo kodowany jako [\\]

    • \"mogą być kodowane jako \\\\\"lub[\\]\"
    • \\"mogą być kodowane jako \\\\\\\\\"lub [\\][\\]\"lub\\[\\]\"

Cofanie
cudzysłowu i ukośnik odwrotny w / G: FILE dosłowne ciągi wyszukiwania Niezależne cytaty i odwrotne ukośniki w pliku dosłownego ciągu wyszukiwania określonego przez / G: plik nie muszą być poprzedzane, ale mogą być.

"i \"są równoważne.

\i \\są równoważne.

Jeśli celem jest znalezienie \\, to przynajmniej wiodący ukośnik odwrotny musi być poprzedzony znakiem ucieczki. Zarówno \\\i \\\\praca.

Jeśli intencją jest znalezienie \ ", to przynajmniej wiodący ukośnik odwrotny musi być poprzedzony. Oba \\"i \\\"działają.

Znak ucieczki cytatu i ukośnik odwrotny w ciągu / G: FILE ciągi wyszukiwania wyrażeń regularnych
Jest to jedyny przypadek, w którym sekwencje specjalne działają zgodnie z oczekiwaniami na podstawie dokumentacji. Cytat nie jest metaznakiem wyrażenia regularnego, więc nie trzeba go usuwać (ale może być). Ukośnik odwrotny jest metaznakiem wyrażenia regularnego, dlatego należy go usunąć.

Limity znaków dla parametrów wiersza poleceń - rozszerzona transformacja ASCII
Znak pusty (0x00) nie może pojawić się w żadnym ciągu w wierszu polecenia. W łańcuchu może pojawić się dowolny inny znak jednobajtowy (0x01 - 0xFF). Jednak FINDSTR konwertuje wiele rozszerzonych znaków ASCII, które znajdzie w parametrach wiersza poleceń, na inne znaki. Ma to duży wpływ na dwa sposoby:

1) Wiele rozszerzonych znaków ASCII nie będzie pasowało do siebie, jeśli zostanie użyty jako ciąg wyszukiwania w wierszu poleceń. To ograniczenie jest takie samo dla wyszukiwań literałowych i wyrażeń regularnych. Jeśli szukany ciąg musi zawierać rozszerzony ASCII, /G:FILEnależy zamiast tego użyć opcji

2) FINDSTR może nie znaleźć pliku, jeśli nazwa zawiera rozszerzone znaki ASCII, a nazwa pliku jest podana w wierszu poleceń. Jeśli plik do przeszukania zawiera rozszerzone ASCII w nazwie, /F:FILEnależy zamiast tego użyć opcji

Oto pełna lista rozszerzonych przekształceń znaków ASCII, które FINDSTR wykonuje na ciągach wiersza poleceń. Każdy znak jest reprezentowany jako dziesiętna wartość bajtu. Pierwszy kod reprezentuje znak podany w wierszu poleceń, a drugi kod reprezentuje znak, w który został przekształcony. Uwaga - ta lista została skompilowana na maszynie w USA. Nie wiem, jaki wpływ mogą mieć inne języki na tę listę.

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

Każdy znak> 0 niewymieniony na powyższej liście jest traktowany jak sam, w tym <CR>i < LF>. Najprostszym sposobem na dołączenie nieparzystych znaków, takich jak <CR>i, <LF>jest umieszczenie ich w zmiennej środowiskowej i użycie opóźnionego rozwijania w argumencie wiersza poleceń.

Limity znaków dla ciągów znalezionych w plikach określonych przez opcje / G: FILE i / F: FILE
W pliku może pojawić się znak nul (0x00), ale działa on jak terminator ciągów C. Wszelkie znaki po znaku nul są traktowane jako inny ciąg znaków, jakby znajdowały się w innym wierszu.

<CR>I <LF>znaki są traktowane jako terminatory linii, które kończą ciąg, a nie uwzględnionych w ciąg.

Wszystkie pozostałe znaki jednobajtowe są doskonale zawarte w ciągu.

Wyszukiwanie plików Unicode
FINDSTR nie może poprawnie przeszukać większości Unicode (UTF-16, UTF-16LE, UTF-16BE, UTF-32), ponieważ nie może wyszukiwać nul bajtów, a Unicode zwykle zawiera wiele nul bajtów.

Jednak polecenie TYPE konwertuje UTF-16LE z BOM na zestaw znaków jednobajtowych, więc takie polecenie jak poniższe będzie działać z UTF-16LE z BOM.

type unicode.txt|findstr "search"

Pamiętaj, że punkty kodu Unicode, które nie są obsługiwane przez twoją aktywną stronę kodową, zostaną przekonwertowane na ?znaki.

Możliwe jest wyszukiwanie UTF-8, o ile szukany ciąg zawiera tylko ASCII. Jednak dane wyjściowe konsoli wielobajtowych znaków UTF-8 nie będą prawidłowe. Ale jeśli przekierujesz dane wyjściowe do pliku, wynik zostanie poprawnie zakodowany UTF-8. Zauważ, że jeśli plik UTF-8 zawiera BOM, wówczas BOM będzie uważany za część pierwszego wiersza, co może uniemożliwić wyszukiwanie pasujące do początku wiersza.

Możliwe jest wyszukiwanie wielobajtowych znaków UTF-8, jeśli umieścisz szukany ciąg w pliku wyszukiwania zakodowanym w UTF-8 (bez BOM) i użyjesz opcji / G.

Koniec linii
FINDSTR przerywa linie natychmiast po każdym <LF>. Obecność lub brak <CR> nie ma wpływu na przerwy w linii.

Wyszukiwanie według podziałów linii
Zgodnie z oczekiwaniami, .metaznak wyrażenia regularnego nie będzie pasował do <CR> lub <LF>. Możliwe jest jednak przeszukiwanie podziału wiersza za pomocą ciągu wyszukiwania wiersza polecenia. Zarówno znaki <CR>, jak i <LF> muszą być wyraźnie dopasowane. W przypadku znalezienia dopasowania wieloliniowego drukowana jest tylko pierwsza linia dopasowania. FINDSTR następnie podwaja się do drugiej linii w źródle i rozpoczyna wyszukiwanie od nowa - coś w rodzaju funkcji „patrz przed siebie”.

Załóżmy, że TEXT.TXT ma te treści (może być w stylu Unix lub Windows)

A
A
A
B
A
A

Potem ten skrypt

@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

daje te wyniki

1:A
2:A
5:A

Przeszukiwanie podziałów wierszy za pomocą opcji / G: FILE jest niedokładne, ponieważ jedynym sposobem dopasowania <CR> lub <LF> jest wyrażenie wyrażenia zakresu klasy wyrażenia regularnego, które umieszcza znaki EOL.

  • [<TAB>-<0x0B>] pasuje do <LF>, ale pasuje również do <TAB> i <0x0B>

  • [<0x0C>-!] pasuje do <CR>, ale pasuje również do <0x0C> i!

    Uwaga - powyższe są symbolicznymi reprezentacjami strumienia bajtów wyrażeń regularnych, ponieważ nie mogę graficznie przedstawić znaków.

Odpowiedź kontynuowana w części 2 poniżej ...

dbenham
źródło
46
Znakomita kompletność. Gdyby tylko wszystkie odpowiedzi w Internecie były takie.
Mike Viens,
1
jakie napotkał problem addpath.batz Q141344 i findstr, które mogą być związane z problemem zawieszania Win7 wymienionych powyżej. Stworzyłem pokój czatu, aby spróbować to wyśledzić, dla każdego, kto jest zainteresowany: chat.stackoverflow.com/rooms/13177/...
matt wilkie
2
EDYCJA - Opisane wyświetlanie znaków kontrolnych jako kropek na XP. Udokumentowano również błędy /Si /Dopcje wynikające z krótkich nazw plików 8.3.
dbenham
1
EDYCJA - 1) Nazwy plików w pliku określonym przez / F: PLIK nie mogą być cytowane. 2) Transformacja rozszerzonych znaków ASCII wpływa zarówno na ciągi wyszukiwania, jak i nazwy plików, gdy są one dostarczane w wierszu poleceń.
dbenham
1
EDYCJA - Dodano błąd polegający na tym, że ostatni wiersz wprowadzanego potoku jest ignorowany, jeśli składa się z jednego znaku bez<LF>
dbenham
64

Odpowiedź ciąg dalszy od części 1 powyżej - napotkałem limit odpowiedzi 30 000 znaków :-(

Ograniczona obsługa wyrażeń regularnych (regex) Obsługa
wyrażeń regularnych przez FINDSTR jest bardzo ograniczona. Jeśli nie ma go w dokumentacji POMOCY, nie jest obsługiwany.

Poza tym obsługiwane wyrażenia regularne są implementowane w całkowicie niestandardowy sposób, tak że wyniki mogą być inne niż można oczekiwać od grep lub perl.

Zakotwiczenia pozycji linii regex ^ i $
^ dopasowują początek strumienia wejściowego, a także dowolną pozycję bezpośrednio po <LF>. Ponieważ FINDSTR również łamie linie po <LF>, proste wyrażenie regularne „^” zawsze dopasuje wszystkie linie w pliku, nawet plik binarny.

$dopasowuje dowolną pozycję bezpośrednio poprzedzającą <CR>. Oznacza to, że ciąg wyrażenia regularnego zawierający $nigdy nie będzie pasował do żadnych wierszy w pliku tekstowym w stylu uniksowym, ani nie będzie pasował do ostatniego wiersza pliku tekstowego Windows, jeśli brakuje znacznika EOL <CR> <LF>.

Uwaga - Jak już wcześniej wspomniano, przesyłanie potokowe i przekierowane do FINDSTR mogło zostać <CR><LF>dołączone, ale nie w źródle. Oczywiście może to mieć wpływ na wyszukiwanie wyrażeń regularnych $.

Każdy ciąg znaków ze znakami przed ^lub po $zawsze nie znajdzie dopasowania.

Opcje pozycyjne / B / E / X
Opcje pozycyjne działają tak samo jak ^i $, z tym wyjątkiem, że działają także w przypadku literalnych ciągów wyszukiwania.

/ B działa tak samo jak ^na początku szukanego wyrażenia regularnego.

/ E działa tak samo jak $na końcu szukanego wyrażenia regularnego.

/ X działa tak samo, jak posiadanie zarówno ^na początku, jak i $na końcu szukanego wyrażenia regularnego.

Granica słowa
\< regex musi być pierwszym terminem w wyrażeniu regularnym. Wyrażenie regularne nie pasuje do niczego, jeśli poprzedzają go inne znaki. \<odpowiada początkowi wejścia, początkowi wiersza (pozycja bezpośrednio po <LF>) lub pozycji bezpośrednio po dowolnym znaku „niebędącym słowem”. Następny znak nie musi być „słowem”.

\>musi być ostatnim terminem wyrażenia regularnego. Wyrażenie regularne nie pasuje do niczego, jeśli podążają za nim inne znaki. \>odpowiada końcowi wprowadzania, pozycji bezpośrednio przed <CR> lub pozycji bezpośrednio poprzedzającej dowolny znak „niebędący słowem”. Poprzedni znak nie musi być „słowem”.

Oto pełna lista znaków „niebędących słowami”, reprezentowanych jako dziesiętny kod bajtu. Uwaga - ta lista została skompilowana na maszynie w USA. Nie wiem, jaki wpływ mogą mieć inne języki na tę listę.

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

Zakresy klas znaków Regex [xy]
Zakresy klas znaków nie działają zgodnie z oczekiwaniami. Zobacz to pytanie: Dlaczego findstr nie obsługuje poprawnie sprawy (w niektórych okolicznościach)? , wraz z tą odpowiedzią: https://stackoverflow.com/a/8767815/1012053 .

Problem polega na tym, że FINDSTR nie zestawia znaków według ich bajtowej wartości kodu (powszechnie uważanej za kod ASCII, ale ASCII jest definiowany tylko od 0x00 - 0x7F). Większość implementacji wyrażeń regularnych traktowałoby [AZ] jak wielkie angielskie litery. Jednak FINDSTR używa sekwencji zestawiania, która z grubsza odpowiada działaniu SORT. Tak więc [AZ] zawiera pełny alfabet angielski, zarówno wielkie jak i małe litery (oprócz „a”), a także nieangielskie znaki alfabetu z znakami diakrytycznymi.

Poniżej znajduje się pełna lista wszystkich znaków obsługiwanych przez FINDSTR, posortowana w kolejności sortowania używanej przez FINDSTR do ustalenia zakresów klas wyrażeń regularnych. Znaki są reprezentowane jako ich dziesiętna wartość bajtu. Uważam, że sekwencja zestawiania jest najbardziej sensowna, jeśli znaki są wyświetlane przy użyciu strony kodowej 437. Uwaga - ta lista została skompilowana na maszynie w USA. Nie wiem, jaki wpływ mogą mieć inne języki na tę listę.

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

Limit terminu dla klasy znaków Regex i
BŁĄD FINDSTR nie tylko jest ograniczony do maksymalnie 15 terminów klasy znaków w wyrażeniu regularnym, ale nie obsługuje poprawnie próby przekroczenia limitu. Użycie 16 lub więcej terminów klas znaków powoduje interaktywne wyskakujące okienko Windows z informacją, że „Narzędzie Find String (QGREP) napotkało problem i musi zostać zamknięte. Przepraszamy za niedogodności”. Tekst wiadomości różni się nieznacznie w zależności od wersji systemu Windows. Oto jeden przykład FINDSTR, który zawiedzie:

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]

Ten błąd został zgłoszony przez użytkownika DagoTips Judago tutaj . Zostało to potwierdzone w systemach XP, Vista i Windows 7.

Wyszukiwanie wyrażeń
regularnych kończy się niepowodzeniem (i może się zawiesić na czas nieokreślony), jeśli zawierają kod bajtowy 0xFF (dziesiętnie 255) Każde wyszukiwanie wyrażenia regularnego zawierające kod bajtowy 0xFF (dziesiętnie 255) zakończy się niepowodzeniem. Nie powiedzie się, jeśli kod bajtu 0xFF jest zawarty bezpośrednio lub jeśli jest domyślnie zawarty w zakresie klasy znaków. Pamiętaj, że zakresy klas znaków FINDSTR nie zestawiają znaków na podstawie wartości kodu bajtu. Postać <0xFF>pojawia się stosunkowo wcześnie w sekwencji zestawiania między <space>i <tab>. Tak więc dowolny zakres klas postaci, który obejmuje oba <space>i <tab>nie powiedzie się.

Dokładne zachowanie zmienia się nieznacznie w zależności od wersji systemu Windows. Windows 7 zawiesza się bez końca, jeśli uwzględniono 0xFF. XP nie zawiesza się, ale zawsze nie może znaleźć dopasowania i od czasu do czasu drukuje następujący komunikat o błędzie - „Proces próbował zapisać do nieistniejącego potoku”.

Nie mam już dostępu do komputera z systemem Vista, więc nie mogłem testować w systemie Vista.

Błąd Regex: .i [^anySet]może pasować do końca pliku Metaznak
wyrażenia regularnego .powinien pasować tylko do dowolnego znaku innego niż <CR>lub <LF>. Istnieje błąd, który pozwala dopasować koniec pliku, jeśli ostatni wiersz w pliku nie jest zakończony przez <CR>lub <LF>. Jednak .nie będzie pasować do pustego pliku.

Na przykład plik o nazwie „test.txt” zawierający pojedynczą linię x, bez kończenia <CR>lub <LF>, będzie pasował do następującego:

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

Ten błąd został potwierdzony na XP i Win7.

To samo wydaje się dotyczyć negatywnych zestawów znaków. Coś takiego [^abc]będzie pasować do końca pliku. [abc]Wydaje się, że pozytywne zestawy znaków działają dobrze. Testowałem to tylko na Win7.

dbenham
źródło
1
findstr ma również problemy z dużymi plikami. Pliki> 2 GB mogą powodować zawieszanie się findstr. Nie zawsze tak się dzieje. Potwierdzając błąd, przeszukałem plik o rozmiarze 2,3 GB, który się nie zawiesił. Zawiesza się nawet podczas wyszukiwania tylko jednego pliku. Obejściem tego problemu jest podłączenie wyjścia typedo findstr.
Rozczarowany
Prawdopodobnie warto także wspomnieć, że findstrobsługuje wiele /c:ciągów wyszukiwania. Wiem, że twoje odpowiedzi to pokazują. Ale jest to coś, co nie zostało udokumentowane; i byłem bardzo zaskoczony, gdy dowiedziałem się o tej funkcji po findstrkilku latach jej używania .
Rozczarowany
@CraigYoung - Masz rację co do źródeł ciągu wyszukiwania. Zredagowałem swoją odpowiedź, dzięki.
dbenham
1
Podczas dalszego dochodzenia wygląda to na odmianę LFudokumentowanego problemu. Zdałem sobie sprawę, że mój plik testowy się nie skończył, LFponieważ użyłem go copyw trybie dołączania do jego utworzenia. Umieściłem sesję wiersza poleceń, aby zademonstrować problem w odpowiedzi ( stackoverflow.com/a/22943056/224704 ). Zauważ, że dane wejściowe nie są przekierowywane, a mimo to wyszukiwanie zawiesza się. Dokładnie to samo polecenie wyszukiwania nie zawiesza się z mniejszymi plikami, które podobnie się nie kończą LF.
Rozczarowany
1
Nowe odkrycie (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 klas postaci) - ErrorLevel = -1073740791 (0xC0000409), okno dialogowe błędu : Find String (QGREP) Utility has stopped working; po usunięciu jednej klasy lub dwóch znaków meta ( *\.) działa ...
aschipfl
7

findstr czasami zawiesza się nieoczekiwanie podczas wyszukiwania dużych plików.

Nie potwierdziłem dokładnych warunków ani rozmiarów granic. Podejrzewam, że każdy plik większy niż 2 GB może być zagrożony.

Miałem z tym mieszane doświadczenia, więc jest to coś więcej niż tylko rozmiar pliku. Wygląda na to, że może być odmianą FINDSTR zawiesza się na XP i Windows 7, jeśli przekierowane dane wejściowe nie kończą się na LF , ale jak pokazano, ten szczególny problem objawia się, gdy dane wejściowe nie są przekierowywane.

Poniższa sesja wiersza poleceń (Windows 7) pokazuje, jak findstrmożna zawiesić się podczas wyszukiwania pliku 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>

Uwaga: zweryfikowałem w edytorze szesnastkowym, że wszystkie linie są zakończone CRLF. Jedyną anomalią jest to, że plik jest kończony ze 0x1Awzględu na sposób copydziałania . Należy jednak pamiętać, że ta anomalia nie powoduje problemów w przypadku „małych” plików .

Dzięki dodatkowym testom potwierdziłem, co następuje:

  • Używanie copyz /bopcją plików binarnych zapobiega dodawaniu 0x1Aznaku i findstrnie zawiesza się na pliku 3 GB.
  • Zakończenie pliku 3 GB innym znakiem powoduje również findstrzawieszenie się.
  • The 0x1APostać nie powoduje żadnych problemów w „małej” pliku. (Podobnie w przypadku innych znaków kończących.)
  • Dodanie CRLFpo 0x1Arozwiązuje problem. ( LFsamo w sobie prawdopodobnie by wystarczyło).
  • Używanie typedo potokowania pliku do findstrprac bez zawieszenia. (Może to być spowodowane efektem ubocznym albo typeczy |tego wstawia dodatkowy końca linii).
  • Użycie przekierowanych danych wejściowych <również powoduje findstrzawieszenie się. Ale tego się oczekuje; jak wyjaśniono w poście dbenham : „przekierowane dane wejściowe muszą kończyć się na LF .
Rozczarowany
źródło
1
+1, jestem w stanie potwierdzić problem na mojej maszynie Win7. Plik o rozmiarze dokładnie 2GiB zawiesił się, gdy nie był to ostatni znak <LF>. Plik o dwa bajty mniejszy nie zawiesił się. Bardzo paskudny!
dbenham
6

Gdy kilka poleceń jest zawartych w nawiasach, a pliki są przekierowywane do całego bloku:

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

... wtedy pliki pozostają otwarte, dopóki polecenia w bloku są aktywne, więc polecenia mogą przesunąć wskaźnik pliku przekierowanych plików. Zarówno polecenia WIĘCEJ, jak i ZNAJDŹ przesuwają wskaźnik pliku Stdin na początek pliku przed jego przetworzeniem, więc ten sam plik może być przetwarzany kilka razy w bloku. Na przykład ten kod:

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

... dają taki sam wynik jak ten:

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

Ten kod:

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

... dają taki sam wynik jak ten:

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

FINDSTR jest inny; to jednak nie przesunąć wskaźnik pliku stdin od aktualnej pozycji. Na przykład ten kod wstawia nowy wiersz po wierszu wyszukiwania:

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

Możemy dobrze wykorzystać tę funkcję za pomocą programu pomocniczego, który pozwala nam przenieść wskaźnik pliku przekierowanego pliku, jak pokazano w tym przykładzie .

To zachowanie zostało po raz pierwszy zgłoszone przez jeb w tym poście .


EDYCJA 2018-08-18 : Zgłoszono nowy błąd FINDSTR

Polecenie FINDSTR ma dziwny błąd, który występuje, gdy to polecenie służy do wyświetlania znaków w kolorze ORAZ wynik takiego polecenia jest przekierowywany do urządzenia CON. Szczegółowe informacje na temat używania polecenia FINDSTR do wyświetlania tekstu w kolorze można znaleźć w tym temacie .

Gdy dane wyjściowe tej formy polecenia FINDSTR są przekierowywane do CON, po wyjściu tekstu w pożądanym kolorze dzieje się coś dziwnego: cały tekst po tym, jak jest wyświetlany jako „niewidoczny” znak, chociaż dokładniejszy opis jest taki, że tekst jest wyjście w postaci czarnego tekstu na czarnym tle. Oryginalny tekst pojawi się, jeśli użyjesz polecenia KOLOR, aby zresetować kolory pierwszego planu i tła na całym ekranie. Jednak gdy tekst jest „niewidoczny”, możemy wykonać polecenie SET / P, więc wszystkie wprowadzone znaki nie pojawią się na ekranie. Tego zachowania można użyć do wprowadzenia haseł.

@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
źródło
2

Chciałbym zgłosić błąd dotyczący sekcji Źródło danych do przeszukania w pierwszej odpowiedzi przy użyciu en dash (-) lub em dash (-) w nazwie pliku.

Mówiąc dokładniej, jeśli zamierzasz użyć pierwszej opcji - nazw plików określonych jako argumenty , plik nie zostanie znaleziony. Gdy tylko użyjesz opcji 2 - stdin poprzez przekierowanie lub 3 - strumień danych z potoku , findstr znajdzie plik.

Na przykład ten prosty skrypt wsadowy:

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

wydrukuje:

Nazwa pliku z en dash:

  1. Jako argument
    FINDSTR: Nie można otworzyć nazwy pliku za pomocą - dash.txt

  2. Jako stdin poprzez przekierowanie
    jestem plikiem z myślnikiem.

  3. Jako strumień danych z potoku
    jestem plikiem z myślnikiem.

Nazwa pliku z em myślnikiem:

  1. Jako argument
    FINDSTR: Nie można otworzyć nazwy pliku za pomocą - dash.txt

  2. Jako stdin poprzez przekierowanie
    jestem plikiem z myślnikiem.

  3. Jako strumień danych z potoku
    jestem plikiem z myślnikiem.

Mam nadzieję, że to pomoże.

M.

matro
źródło
1
Cześć matro, chociaż twoje komentarze mogą być poprawne, nie jestem pewien, czy nie odnoszą się do rzeczywistego pytania.
Wai Ha Lee
Uważam, że jest to problem związany z Unicode, którego FINDSTR nie obsługuje. Przekierowanie CMD.EXE może poprawnie otworzyć nazwę pliku za pomocą Unicode, podobnie jak polecenie TYPE. Ale gdzieś wzdłuż linii FINDSTR konwertuje zarówno en-dash, jak i em-dash na normalny, i oczywiście system operacyjny nie może znaleźć tej nazwy. Jeśli utworzysz inny plik, zastępując myślnik en-myślnikiem i / lub em-myślnikiem, FINDSTR przeszuka plik myślnika, jeśli zostanie mu nadana nazwa zawierająca myślnik lub myślnik.
dbenham
Sklasyfikowałbym ten problem raczej jako ograniczenie niż błąd.
dbenham
W rzeczywistości nie jest to tak bardzo problem z Unicode, jak rozszerzony ASCII. Udokumentowałem już ten problem w mojej oryginalnej odpowiedzi pod nagłówkiem Limity znaków dla parametrów wiersza poleceń - Rozszerzona transformacja ASCII . FINDSTR przekształca wiele rozszerzonych kodów ASCII w „pokrewne” prawdziwe ASCII, w tym en-dash i em-dash.
dbenham,
1

findstrPolecenie ustawia ErrorLevel(lub wyjście) kodu do jednego z następujących wartości, jako że nie ma żadnych nieprawidłowych lub niezgodne przełączniki i ma ciąg wyszukiwania przekracza odpowiadającej maksymalnej długości:

  • 0 gdy w jednym wierszu napotkane zostanie co najmniej jedno dopasowanie we wszystkich określonych plikach;
  • 1 Inaczej;

Uważa się, że wiersz zawiera dopasowanie, gdy:

  • nie /Vpodano żadnej opcji i wyrażenie wyszukiwania występuje co najmniej raz;
  • /Vopcja jest podana i wyrażenie wyszukiwania nie występują;

Oznacza to, że /Vopcja zmienia również zwracany ErrorLevel, ale nie tylko go przywraca!

Na przykład, jeśli masz plik test.txtz dwoma wierszami, z których jeden zawiera ciąg, texta drugi nie, oba findstr "text" "test.txt"i findstr /V "text" "test.txt"zwracają jeden ErrorLevelz nich 0.

Zasadniczo możesz powiedzieć: jeśli findstrzwraca przynajmniej linię, ErrorLeveljest ustawiona na 0, w przeciwnym razie 1.

Zauważ, że /Mopcja nie wpływa na ErrorLevelwartość, tylko zmienia wynik.

(Ze względu na kompletność: findpolecenie zachowuje się dokładnie tak samo w odniesieniu do /Vopcji i ErrorLevel; /Copcja nie ma wpływu ErrorLevel).

aschipfl
źródło
1

FINDSTR ma błąd koloru, który opisałem i rozwiązałem na /superuser/1535810/is-there-a-better-way-to-mitigate-this-obscure-color-bug-when-piping-to -findstr / 1538802? noredirect = 1 # comment2339443_1538802

Podsumowując ten wątek, błąd polega na tym, że jeśli dane wejściowe są przesyłane do FINDSTR w nawiasowym bloku kodu, wbudowane kody ucieczki ANSI przestają działać w poleceniach wykonanych później. Przykładem wbudowanych kodów kolorów jest: echo %magenta%Alert: Something bad happened%yellow%(gdzie magenta i żółty to zmienne zdefiniowane wcześniej w pliku .bat jako odpowiadające im kody ucieczki ANSI).

Moim początkowym rozwiązaniem było wywołanie podprogramu „nic nie rób” po FINDSTR. W jakiś sposób połączenie lub powrót „resetuje” wszystko, co wymaga zresetowania.

Później odkryłem inne rozwiązanie, które prawdopodobnie jest bardziej wydajne: umieść frazę FINDSTR w nawiasach, jak w poniższym przykładzie: echo success | ( FINDSTR /R success ) Umieszczenie frazy FINDSTR w zagnieżdżonym bloku kodu wydaje się izolować błąd kodu koloru FINDSTR, aby nie wpływał na to, co znajduje się poza zagnieżdżonym blok. Być może ta technika rozwiąże również inne niepożądane skutki uboczne FINDSTR .

Dolores Stevens
źródło
Świetne znalezisko. Ale twoje reguły można uprościć (przynajmniej na moim korporacyjnym komputerze z systemem Windows 10). Funkcja FINDSTR zapobiega działaniu wszystkich sekwencji ucieczki konsoli dla kolejnych poleceń w tym samym bloku poleceń. Nie ma znaczenia, czy FINDSTR odczytuje potok, przekierowane wejście lub plik. Błąd sekwencji ucieczki nie jest ograniczony do kodów kolorów. Blok poleceń to dowolny zestaw poleceń w nawiasach i / lub polecenia połączone przez &, && lub ||
dbenham
@dbenham: Niezła generalizacja problemu. Czy wiesz, czy moje rozwiązanie - zagnieżdżanie frazy FINDSTR w nawiasach - działa również w przypadku ogólnym? A czy wiesz, czy moje rozwiązanie ma jakieś niepożądane skutki uboczne?
Dolores Stevens
Nie przeprowadziłem żadnych wyczerpujących testów, ale tak, zagnieżdżone nawiasy wydają się być ogólnym rozwiązaniem i nie mogę wymyślić żadnych możliwych niepożądanych efektów ubocznych.
dbenham
-1

/ D wskazówka dla wielu katalogów: umieść listę katalogów przed wyszukiwanym ciągiem. Wszystkie działają:

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

Zgodnie z oczekiwaniami ścieżka jest względna do lokalizacji, jeśli nie uruchamiasz katalogów \. Otaczanie ścieżki "jest opcjonalne, jeśli w nazwach katalogów nie ma spacji. Zakończenie \jest opcjonalne. Dane wyjściowe lokalizacji będą zawierać podaną przez ciebie ścieżkę. Będzie działać z otoczeniem listy katalogów lub bez niej ".

Gordon
źródło
Nie widzę tu niczego nieudokumentowanego. Opcja / D jest opisana we wbudowanej pomocy. To nie jest pytanie o ogólne wskazówki dotyczące korzystania z FINDSTR. Ma ściśle wymieniać nieudokumentowane funkcje, ograniczenia i / lub błędy.
dbenham
1
@dbenham prawda, to nie jest tak naprawdę nieudokumentowane, ale znalazłem, że musiałem przekopać się z findstr, aby uzyskać pożądane wyniki i dzielę się tym, co znalazłem DID, aby ludzie nie marnowali czasu na eksperymentowanie z poleceniami, które NIE działają. hth (przykro mi, że nie lubisz mojego wkładu - miał on być jedynie konstruktywny)
Gordon
IMHO przełącznik / D jest wyraźnie opisany we wbudowanej pomocy: /D:dirlist Search a semicolon-delimited list of directoriesi jest umieszczony przed ciągiem wyszukiwania, więc nie rozumiem, co dokładnie jest „znalezione” w przełączniku / D (i jakie są polecenia, które NIE działają ") ...
Aacini
@Aacini w wielu językach kolejność atrybutów nie ma znaczenia. findstrNajpierw rozumiem dokumentację dla list / D. Tak, nie mam żadnych argumentów w związku z dokumentowaniem funkcji, po prostu nie udokumentowano gotcha, że ​​kolejność atrybutów ma znaczenie. Wykonuję bardzo mało pracy z wierszem poleceń, więc kiedy brukowałem polecenie, nie wiedząc, że kolejność robi różnicę, po prostu dodawałem atrybuty, kiedy do nich dotarłem (i alfabetycznie C poprzedza D). Byłem naprawdę sfrustrowany i podzieliłem się swoim doświadczeniem dla każdego, kto nie pracuje zbyt wiele z wierszem poleceń.
Gordon
1
Kolejność opcjonalnych atrybutów zwykle nie ma znaczenia. findstrDokumentacja określić, że stringsjest to NIE opcjonalne i że należy go umieścić po opcjonalnych atrybutów i przed opcjonalnym listy nazw. Jeśli „znalezione” to to, że użycie polecenia bez przestrzegania formatu użycia powoduje błąd, to taki punkt jest dobrze udokumentowany. Zobacz Składnia polecenia : „Składnia pojawia się w kolejności, w której należy wpisać polecenie i wszelkie parametry, które po nim następują”
Aacini