4

У нас работает веб-приложение, в котором вы можете ввести регулярное выражение в поле поиска, и оно возвращает совпадения из базы данных.

Вот пример того, как могут выглядеть записи базы данных. Они разделены запятыми (представьте, что каждая запись - это семья - каждая семья может содержать от 1 до n записей):

record1: "john doe"<john@email.com>;male,"jane doe"<jane@email.com;female
record2: "john smith"<jsmith@email.com>
record3: "smith, jane"<jane@smith.com>

Что мне нужно сделать, это ввести регулярное выражение, поэтому я получаю только первую запись. В рабочем сценарии выводом будет все до разделителя:

record1: "john doe"<john@email.com>;male
record2: "john smith"<jsmith@email.com>
record3: "smith, jane"<jane@smith.com>

На самом деле, все мои попытки видеть запятую в «кузнец, джейн» как разделитель.

Как игнорировать запятую, если она в кавычках? (Для проверки на будущее, способность игнорировать запятые в одинарных кавычках тоже будет хорошей)

Я могу использовать только регулярные выражения, а не awk/sed и т.д., А разновидность регулярных выражений - POSIX Extended.

4 ответа4

1

Вы не можете надежно сделать это с помощью регулярных выражений. Лучшее, что вы сможете сделать, это уродливый хак, основанный на куче предположений, которые гарантированно сломаются в конце концов, если вы решитесь внедрить такой код в производство. (Если вы не можете сделать это с огневой мощью полностью вооруженного и работающего движка регулярных выражений Perl, то вы, конечно, не сможете сделать это с расширенными регулярными выражениями POSIX.)

Короче говоря, чтобы надежно решить эту проблему, вам нужно будет найти способ расширить любой код, с которым вы работаете, чтобы он мог использовать библиотеку синтаксического анализа CSV, или, если это не удалось, вам придется написать парсер

Конечно, если вы не можете изменить код, который обрабатывает файлы, о которых идет речь, то вы застряли с отвратительными взломами, что в этом случае вызывает сожаление, так как я не вижу действительно надежного способа получения желаемого результата с регулярными выражениями POSIX в качестве единственного инструмента.

1

Блики: вы должны подробно среду немного больше похоже на комментарии указывают.

Вот одна попытка моей оболочки Unix с sed
Да, я знаю, что вы не хотите использовать sed , но это может помочь вам построить регулярное выражение в вашей среде.

data.txt: 
"john doe"<john@email.com>;male,"jane doe"<jane@email.com;female
john_doe"<john@email.com>;male,"jane doe"<jane@email.com;female

# sed -n 's|^\("[^"]\+"[^,]\+\).*|\1| p' data.txt 
"john doe"<john@email.com>;male

Идея регулярного выражения заключается в том, чтобы перепрыгнуть через первую пару двойных кавычек, а затем искать запятую.
Это не удастся, если нет двойных кавычек.
Его можно масштабировать для использования одинарных кавычек.

Обновление:
Ищите @ а затем , ...

data.txt: 
"john doe"<john@email.com>;male,"jane doe"<jane@email.com;female
john_doe"<john@email.com>;male,"jane doe"<jane@email.com;female

# sed -n 's|\([^@]\+[^,]\+\),.*|\1| p' data.txt 
"john doe"<john@email.com>;male
john_doe<john@email.com>;male

Теперь вы получаете как регистры, так и регистры без имени строки или даже <> переноса.
Но ваша проблема в зависимости от , - разрывы для записи2 и записи3, где у вас есть одно электронное письмо и без запятой. По-прежнему будет работать, если вы заставили , в конце каждой записи.

0

Попытка игнорировать запятую внутри кавычек проблематична, потому что запятая, которую вы хотите найти, также "в кавычках" (конечная цитата "john doe" и открытая цитата "jane doe"). Если вы не предполагаете, что первая цитата существует, вам будет трудно сделать это различие.

Попробуйте это вместо этого:

^[^<]+<[^>]*>[^,\s]*

Я предполагаю, что каждая запись будет иметь <email> и любая запятая после электронного письма будет означать новую запись. Это просто обменяет одно предположение на другое, но в моем тесте это сработало.

0

Используйте regex, чтобы изменить разделитель, если он заключен в кавычки с чем-то вроде tab:

Шаблон ((?:[^, "] |" [^ "] *")+),
Заменить \1 \т

Затем разделить по новому разделителю

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .