Ваше выражение соответствует всем строкам со словом "github
" в них.Давайте посмотрим, почему:
/(?<!golang).*github/
будет соответствовать до тех пор, пока Perl может настроить .*
так, чтобы оно совпадало с количеством символов, достаточным для того, чтобы не встретиться с ситуацией, в которой ему непосредственно предшествует golang
.Реггекс, будучи жадным, .*
будет совпадать столько, сколько может, при этом оставаясь равным остатку шаблона.
Так что, если ваша строка
golang is a language used in github
Регулярное выражение может соответствоватьприсвоение строки различным частям:
(?<!golang)
совпадение в начале строки .*
получает "golang is a language used in
" github
получает"github
"
Потенциально дорогостоящий способ выполнить то, что вы хотели:
/^(?:(?!golang).)*github/
Он работает, следя за тем, чтобы ни один из символов, предшествующих "github
", не начиналсяпоследовательность "golang
".
Итак,
echo "java is a language used in github" | perl -ne 'print q!Not golang: !, /^(?:(?!golang).)*github/ ? q!true! : q!false!'
выведет Not golang: true
, а
echo "golang is a language used in github" | perl -ne 'print q!Not golang: !, /^(?:(?!golang).)*github/ ? q!true! : q!false!'
выведет Not golang: false
.
Другой (менее запутанный) способ - выполнить два последовательных теста:
/^(.*)github/ and $1 !~ /golang/
Если вы выполняете десятки или сотни тысяч строк, возможно, протестируйте оба способа, чтобы найти более быстрый