регулярний вираз для відповідності EOF


90

У мене є деякі дані, які виглядають так

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

Я використовую цей регулярний вираз, щоб відповідати іменам

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

який працює здебільшого, але файл різко закінчується після останнього слова, що означає, що останнє значення не закінчується \r\n, \nабо ,закінчується EOF. Чи є спосіб зіставити EOF у регулярному виразі, щоб я міг це правильно вказати у цій другій групі?


Ви намагаєтеся захопити всі імена в одній групі або одній групі захоплення на ім'я?
Andrew Hare

одне, що потрібно зробити, коли виникають проблеми з регулярним виразом, - це спробувати елементи вашого шаблону ізольовано. якщо вас турбує маркер в кінці, протестуйте свій вираз без нього.
akf

просто хотів додати чудовий сайт для тестування регулярних виразів
northpole


@Sinan - я згоден; об'єднано
Марк Гравелл

Відповіді:


160

Відповідь на це запитання \Zзайняв у мене деякий час, щоб зрозуміти це, але це працює зараз. Зверніть увагу, що навпаки, \Aзбігається з початком цілого рядка (на відміну від початку одного рядка ^та $збігається з ним).


5
Просто зверніть увагу, якщо ви шукаєте таке функціонування в netbeans для пошуку файлів проекту , на відміну від пошуку у файлах , наступне буде поводитися по-різному ... (\s*)\?>(\s*)\Z... і після ще кількох копань ось що буде працювати в папці проекту : (\s*)\?>(\s*)(\n*)(\W)\Z FYI: це для заміни всіх закритих php-тегів розривами рядків у кінці файлу.
MediaVince

1
Виявляється, \Aтакож працює у Visual Studio пошук і заміна. Як завжди використовую подібні речі з обережністю, але це заощадило мені тонну ручного возитися, коли я був щасливий, що насправді вчинив би правильно.
Steve Pettifer

Поки я використовую Scannerклас Java для читання всього файлу одночасно; якщо я використовую \Zяк роздільник, кінцевий символ нового рядка обрізаний. Коли я змінив роздільник на \z, кінцевий символ нового рядка зберігся. Здається, відповідь Мартіна Дорі стосується і Java.
mmdemirbas

24

EOF насправді не є персонажем. Якщо у вас є багаторядковий рядок, тоді '$' буде відповідати кінці рядка, а також кінці рядка.

У Perl та його братах, \Aі \Zзбігаються з початком і кінцем рядка, повністю ігноруючи розриви рядків.

Розширення GNU для регулярних виразів POSIX використовують \`і \'для тих самих речей.


17

У Visual Studio, ви можете знайти EOF подобається так: $(?![\r\n]). Це працює незалежно від того, чи закінчуються ваші рядки CR, CRLF або просто LF.

Як бонус, ви можете переконатись, що всі ваші файли коду мають остаточний маркер нового рядка таким чином:

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

Як це працює:

Знайдіть будь-який кінець рядка (збіг нульової ширини), якому не передує CR або LF, а також не слід CR або LF. Деякі думки покажуть вам, чому це працює!

Зверніть увагу, що вам слід замінити потрібний символ закінчення рядка, будь то CR, LF або CRLF.


У Visual Studio 2019 є помилка, коли заміна всього цього може призвести до додавання двох нових рядків до кінця файлу. Я думаю, це пов’язано з опцією автоматичного вставлення нового рядка при збереженні.
Стевойсяк

9

Порівняйте поведінку запропонованого \ Z Райана \ z з \ z:

$ perl -we 'my $ corpus = "привіт \ n"; $ корпус = ~ s / \ Z / world / g; print (": $ corpus: \ n") '
:Привіт Світ
світ:
$ perl -we 'my $ corpus = "привіт \ n"; $ корпус = ~ s / \ z / world / g; print (": $ corpus: \ n") '
:Здрастуйте
світ:
$ 

perlre sez:

\ Z Збіг лише в кінці рядка або перед новим рядком в кінці
\ z Збіг лише в кінці рядка

Переклад тесту на Ruby (1.8.7, 1.9.2) поводиться так само.


2

Вам справді доводиться фіксувати роздільники? Якщо ні, цей регулярний вираз повинен бути всім необхідним:

/\w+/

Це передбачає, що всі підрядки, яким ви хочете відповідати, складаються повністю із символів слова, як у вашому прикладі.



2

Нещодавно я шукав щось подібне, але JavaScript.

Помістивши це тут, щоб кожен, хто має таку ж проблему, міг отримати вигоду

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

В основному це відповідало б кінці рядка, за яким не слід повертати каретку або нові символи рядка. По суті, це те саме, що \Zі для JavaScript.


1

Якщо припустити, що ви використовуєте належний модифікатор, що змушує обробляти рядок у цілому (а не рядок за рядком - і якщо \ n працює для вас, ви використовуєте його), просто додайте ще одну альтернативу - кінець рядка: (\ r \ n | \ n |, | $)


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.