Я ищу регулярное выражение, которое соответствует строке из двух строк со следующей характеристикой:
[any number of any character]"[any number of any character][not a space and not a backslash followed by the char n]"
[any number of spaces]"[not a space][any number of any character]"
то есть оно должно соответствовать: 1)
abc def "ghi jkl"
"mno pqr"
но нет 2)
abc def "ghi jkl "
"mno pqr"
ни 3)
abc def "ghi jkl"
" mno pqr"
ни 4)
abc def "ghi jkl\n"
"mno pqr"
Я использую регулярное выражение: ".*[^\s]"\s+"[^\s].*"
Это хорошо работает с 1), 2) и 3), но явно не с 4).
Ваше недавнее изменение изменено с [not a space and not the string '\n']
на [not a space and not a backslash followed by the char n]
. Оба сбивают с толку, но особенно текущий, потому что обратная косая черта, за которой следует символ «n», означает два символа, а не экранированный «n»; то есть символ новой строки (\n). Предлагаю [a character other than a space or newline character]
.
<<обратная косая черта, за которой следует символ n>> означает обратную косую черту, за которой следует символ n, буквально, т. е. 2 символа, а не новую строку.
Вы могли бы избежать всей путаницы в своем вопросе, если бы правильно написали строки в кавычках. Например, вместо abc def "ghi jkl\n"
надо было написать "abc def \"ghi jkl\\n\""
. То, что вы сделали, похоже на запись массива как 1, 2, 3
, а не [1, 2, 3]
. Я понижаю голосование за неясность вашего вопроса.
Я только что перечислил текст, который должен и не должен совпадать. В тексте есть строка \n" буквально, а не \\n\".
Если вы хотите извлечь эти две подстроки, вы можете использовать:
^(?m)[^"\r\n]+"(\S.*\S)"\s+"(\S.*\S)"\s*$
а если нет:
^(?m)[^"\r\n]+"\S.*\S"\s+"\S.*\S"\s*$
К сожалению, предложенное регулярное выражение некорректно совпадает, даже если текст, заключенный в двойные кавычки в первой строке, заканчивается обратной косой чертой, за которой следует буква n, например abc def "ghi jkl\n" regex101.com/r/EArk1N/1
Отредактировал мой ответ на основе отрицательного анализа Sina-sarshar-pour ответа:
.*[^\s](?<!\b\\n\b)"\s+"[^\s].*
https://stackoverflow.com/a/78631164/1856745
Тесты:
Возвышенный текст.
https://regex101.com/r/nb0dQy/1
К сожалению, предлагаемое регулярное выражение некорректно не соответствует, даже если текст, заключенный в двойные кавычки в первой строке, заканчивается обратной косой чертой, например abc def "ghi jkl\" regex101.com/r/aJ3iG1/1, и если он заканчивается на n не предшествует обратная косая черта, например abc def "ghi jkln" regex101.com/r/JmTHwR/1
Этого не было в первой версии вашего вопроса. Будет ли шаблон вашего текста выглядеть так: [любое количество любых символов]"[любое количество любых символов][(не пробел) и ((не обратная косая черта) или (не обратная косая черта, за которой следует символ n))] " [любое количество пробелов]"[не пробел][любое количество любых символов]"
В первой версии я написал <<не пробел и не строку '\n'>>, подразумевая <<не пробел и не обратную косую черту, за которой следовал символ n>>
Насколько я понимаю, вы хотите определить, соответствуют ли строки следующему регулярному выражению.
(?x) # invoke extended (aka free-spacing) mode
^ # match beginning of the string
[^"\n]* # match zero or more chars other than line terminators
# and double-quotes
" # match a double-quote
[^"\n]* # match zero or more chars other than line terminators
# and double-quotes
(?<! # begin a negative lookbehind
\ # match a space
| # or
\\n # match a backslash followed by n
) # end negative lookbehind
" # match a double-quote
\n # match a newline
\ * # match zero or more spaces
" # match double-quote
[^ "\n] # match a character other than a space, double-quote or newline
[^"\n]* # match zero or more chars other than line terminators
# and double-quotes
" # match a double-quote
\n? # optionally match a newline
$ # match end of string
Я написал это в расширенном режиме (то есть со свободным интервалом), чтобы прояснить свои предположения. Если какие-либо из них неверны, вы можете внести необходимые изменения. Вы написали, например, «любое количество любых символов». Я предположил, что вы на самом деле имели в виду «любое количество любых символов, кроме двойных кавычек и новых строк». Точно так же я предположил, что фраза «без пробела или обратной косой черты, за которой следует «n»» означает, что строка, предшествующая второй двойной кавычке, не может заканчиваться пробелом или обратной косой чертой, за которой следует «n».
Это регулярное выражение соответствует следующим двум (двухстрочным) строкам.
a c"d1 %"
"&g i"
"9"
"&"
Он не соответствует следующим трем строкам: первая, потому что пробел не разрешен перед второй двойной кавычкой, вторая, потому что обратная косая черта, за которой следует 'n'
, не может предшествовать второй двойной кавычке, а третья, потому что пробел не разрешен после третья двойная кавычка.
д а"фе" "3ч дж"
c"d1 \n" "&г я"
а"де f%x" "&12"
Демонстрация регулярных выражений
Обратите внимание, что я выбрал механизм регулярных выражений PCRE2 по ссылке выше, но предложенное мной регулярное выражение не использует каких-либо расширенных функций регулярных выражений, поэтому оно должно быть совместимо с большинством механизмов регулярных выражений.
1
К сожалению, предложенное регулярное выражение некорректно совпадает, даже если текст, заключенный в двойные кавычки в первой строке, заканчивается обратной косой чертой, за которой следует буква n, например abc def "ghi jkl\n" regex101.com/r/CKSDKv/1
Я понимаю разницу между символом новой строки и последовательностью двух символов, состоящей из обратной косой черты и буквы «n», поэтому я написал <<не пробел и не строка '\n'>> и, чтобы быть более понятным, Я отредактировал его <<не пробел и не обратная косая черта, за которой следует символ n>>, что, я думаю, означает не пробел и не обратную косую черту, за которой следует символ n буквально, т.е. 2 символа (иначе я бы написал <<не a пробел, а не новая строка>>.
Использование негативного ретроспективного анализа
.*".*(?<! |\\n)"\n\s*"(?! )..*"
Ты прав. если вы измените \s+ на \s*, это тоже сработает. В вопросе указано любое количество пробелов во второй строке, но я использовал \s+, который соответствует строке только в том случае, если во второй строке существует хотя бы один пробел. Так что моя ошибка. Новый ответ будет Демо.*".*((?<! |\\n))"\n\s*"(?! )..*"
Я обновил свой первоначальный ответ
Обновил свой ответ на основе вашего отрицательного прогноза!
В видимости вы можете избежать негативного просмотра, написав .*".*((?<! |\\n))"\n\s*"[^ \n].*"
.
Есть ли причина использовать группу захвата, а не группу без захвата? Если механизм регулярных выражений поддерживает группы без захвата (большинство из них поддерживают), лучше всего использовать группы захвата только тогда, когда вы делаете обратную ссылку на их содержимое или намереваетесь использовать их содержимое позже в своем коде. Если ваш код содержит группу захвата, в то время как группа без захвата будет делать это, читатели вашего кода могут предположить, что содержимое группы будет использоваться позже в вашем коде, и тратить время на его поиск. Ничего особенного, конечно.
Отличный улов @CarySwoveland! Простое удаление группы захвата дает большой выигрыш в производительности (на 1000 вызовов меньше на 30 миллисекунд). Удаление отрицательного просмотра вперед также дает выигрыш в производительности, но очень небольшой (0,2 миллисекунды на 1000 вызовов).
Возможно, вы захотите отредактировать свой ответ, после чего я удалю свои комментарии, поскольку они больше не будут актуальны, а затем вы можете исправить ситуацию, удалив свои комментарии.
@CarySwoveland, эти разговоры в комментариях отлично подходят для будущих читателей. Довольно мало информации о производительности. Я бы хотел сохранить это
Тем временем я обновил свой первоначальный ответ, чтобы удалить групповые снимки.
Попробуйте:
"\S.*\S"\s+"\S.*\S"
? Вам нужно полное совпадение? Вы хотите извлечь те, что в кавычках?^(?m)[^"\r\n]+"\S.*\S"\s+"\S.*\S"\s*$
. Это действительно?abc def "s" "s"