wyrażenie regularne, aby dopasować EOF


90

Mam takie dane

john, dave, chris
rick, sam, bob
joe, milt, paul

Używam tego wyrażenia regularnego, aby dopasować nazwy

/(\w.+?)(\r\n|\n|,)/

która działa w większości przypadków, ale końce plików nagle po ostatnim słowo oznaczające ostatnią wartość nie kończy się \r\n, \nalbo ,kończy się EOF. Czy istnieje sposób na dopasowanie EOF w wyrażeniu regularnym, abym mógł to poprawnie umieścić w drugiej grupie?


Czy próbujesz przechwycić wszystkie nazwy w jednej grupie czy jedną grupę przechwytywania na nazwę?
Andrew Hare

jedną rzeczą do zrobienia, gdy masz problem z wyrażeniem regularnym, jest wypróbowanie pojedynczych elementów wzorca. jeśli martwisz się o token na końcu, przetestuj swoje wyrażenie bez niego.
akf

chciałem tylko dodać świetną witrynę do testowania wyrażeń regularnych
northpole


@Sinan - zgadzam się; połączone
Marc Gravell

Odpowiedzi:


160

Odpowiedź na to pytanie \Zzajęła mi trochę czasu, zanim to rozgryzłem, ale teraz działa. Zauważ, że odwrotnie, \Amecze początkiem całego łańcucha znaków (w przeciwieństwie do ^i $dopasowanie początek jednej linii).


5
Tylko uwaga, jeśli szukasz takiej funkcjonalności w netbeans do wyszukiwania plików projektu w przeciwieństwie do wyszukiwania w plikach , poniższe będą zachowywać się inaczej ... (\s*)\?>(\s*)\Z... i po kilku dalszych kopiach tutaj jest to, co działałoby w folderze projektu : (\s*)\?>(\s*)(\n*)(\W)\Z FYI: ma to na celu zastąpienie wszystkich zamykających tagów php znakami końca linii na końcu pliku.
MediaVince

1
Okazuje się, że \Adziała również w programie Visual Studio znajdź i zamień. Jak zawsze używaj takich rzeczy ostrożnie, ale zaoszczędziło mi to mnóstwa ręcznego bałaganu, gdy byłem szczęśliwy, że faktycznie zrobi to dobrze.
Steve Pettifer

Podczas gdy używam Scannerklasy Javy do odczytu całego pliku naraz; jeśli \Zużyję jako separatora, obcięty zostanie końcowy znak nowej linii. Kiedy zmieniłem separator na \z, zachowywany jest końcowy znak nowej linii. Wydaje się, że odpowiedź Martina Doreya odnosi się również do Javy.
mmdemirbas

24

EOF w rzeczywistości nie jest postacią. Jeśli masz ciąg wieloliniowy, „$” dopasuje koniec ciągu, jak i koniec linii.

W Perlu i jego braciach \Ai \Zdopasuj początek i koniec łańcucha, całkowicie ignorując znaki końca linii.

Rozszerzenia GNU do wyrażeń regularnych POSIX używają \`i \'do tego samego.


17

W programie Visual Studio można znaleźć EOF tak: $(?![\r\n]). Działa to niezależnie od tego, czy zakończenia linii to CR, CRLF, czy tylko LF.

Jako bonus możesz upewnić się, że wszystkie pliki z kodem mają końcowy znacznik nowej linii, taki jak:

               Find What: (?<![\r\n])$(?![\r\n])
            Replace With: \r\n
 Use Regular Expressions: checked
Look at these file types: *.cs, *.cshtml, *.js

Jak to działa:

Znajdź dowolny koniec wiersza (dopasowanie o zerowej szerokości), który nie jest poprzedzony literami CR ani LF, a także nie występuje po nim CR ani LF. Pewna myśl pokaże Ci, dlaczego to działa!

Zauważ, że powinieneś Zastąpić żądanym znakiem końca linii, czy to CR, LF czy CRLF.


W programie Visual Studio 2019 występuje błąd polegający na tym, że wykonanie zamiany wszystkiego z tym może spowodować dodanie dwóch nowych linii na końcu pliku. Myślę, że ma to coś wspólnego z opcją automatycznego wstawiania nowej linii przy zapisywaniu.
Stevoisiak

9

Porównaj zachowanie sugerowanego przez Ryana \ Z z \ z:

$ perl -we 'my $ corpus = "witaj \ n"; $ corpus = ~ s / \ Z / world / g; print (": $ corpus: \ n") '
:Witaj świecie
świat:
$ perl -we 'my $ corpus = "witaj \ n"; $ korpus = ~ s / \ z / świat / g; print (": $ corpus: \ n") '
:Witaj
świat:
$ 

perlre sez:

\ Z Dopasowuje tylko na końcu łańcucha lub przed nową linią na końcu
\ z Dopasuj tylko na końcu łańcucha

Tłumaczenie przypadku testowego na Rubiego (1.8.7, 1.9.2) zachowuje się tak samo.


2

Czy naprawdę musisz przechwytywać separatory linii? Jeśli nie, to to wyrażenie regularne powinno wystarczyć:

/\w+/

Zakłada się, że wszystkie podciągi, które chcesz dopasować, składają się wyłącznie ze znaków słownych, jak w twoim przykładzie.



2

Ostatnio szukałem czegoś takiego, ale JavaScript.

Umieszczając to tutaj, aby każdy, kto ma ten sam problem, mógł skorzystać

var matchEndOfInput = /$(?![\r\n])/gm;

Zasadniczo pasowałoby to do końca wiersza, po którym nie następuje powrót karetki ani znaki nowego wiersza. W istocie jest to to samo, co \Zpoza JavaScriptem.


1

Zakładając, że używasz odpowiedniego modyfikatora wymuszającego traktowanie ciągu jako całości (nie linii po linii - i jeśli \ n działa, to używasz), po prostu dodaj inną alternatywę - koniec łańcucha: (\ r \ n | \ n |, | $)


Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.