Вам нужно использовать жадный жадный жетон для достижения этой цели. Используйте это регулярное выражение,
\bjson\b(?:(?!\bfrom\b).)+\bjson\b
Это выражение (?:(?!\bfrom\b).)+
будет соответствовать любому тексту, который не содержит from
как целое слово внутри него.
Regex Demo
Для сопоставления всей строки вы можете использовать,
^.*\bjson\b(?:(?!\bfrom\b).)+\bjson\b.*$
Как вы и хотели в своем посте, это регулярное выражение будет соответствовать строке, пока не найдет строку, где from
не появляется между двумя json
с
Демонстрация регулярных выражений с полным совпадением строк
Edit:
Почему регулярное выражение OP select.*json.*?(?<!from)json.*from.*
не работает как ожидалось
Ваше регулярное выражение начинает совпадать с select
, а затем .*
совпадает настолько, насколько это возможно, при этом убедившись, что оно находит json
впереди, за которым следуют некоторые необязательные символы, а затем снова ожидает найти строку json
, затем .*
снова сопоставляет некоторые символы, затем ожидает найти from
и, наконец, использовать .*
ноль или более необязательных символов.
Давайте рассмотрим пример строки, которая должна соответствовать.
select json from json json XXXX
У него есть две json
строки без from
между ними, поэтому они должны совпадать, но это не так, потому что в вашем регулярном выражении порядок или присутствие json и from фиксированы, что составляет json
, затем снова json
затем from
, что не так в этой строке.
Вот демонстрация Java-кода
List<String> list = Arrays.asList("select json,json from XXX","select json from json XXXX","select json,json from json XXX","select json from json json XXXX");
list.forEach(x -> {
System.out.println(x + " --> " + x.matches(".*\\bjson\\b(?:(?!\\bfrom\\b).)+\\bjson\\b.*"));
});
печать
select json,json from XXX --> true
select json from json XXXX --> false
select json,json from json XXX --> true
select json from json json XXXX --> true