Esto parece funcionar en BSDsed
:
$ echo -e "foo bar\nfoo\nbar" | sed -n '/foo/{/bar/p;}'
foo bar
Al igual que dos capas de anidamiento:
$ echo -e "foo bar\nfoo\nbar" | sed -n '/foo/{/bar/{p;};}'
foo bar
Если вы используете Perl (язык ), а не какой-либо инструмент, использующий Perl -совместимые регулярные выражения, нет причин ограничивать себя только одним регулярным выражением.
Что-то вроде этого будет соответствовать только незакомментированной строке:
$ perl -ne 'print if not m,^\s*//, and /\bfoobar\b/' < file.txt
foobar # match me
Даже с другими утилитами или не -регулярными выражениями Perl проще всего использовать несколько регулярных выражений:
$ < file.txt grep -ve '//' | grep '\<foobar\>'
foobar # match me
Если вместо этого вы ограничены одним регулярным выражением Perl, это должно работать:
grep -P '^\s*+(?!//).*\bfoobar\b.*$' file.txt
\s*+
является "притяжательным" выражением , которое соответствует всем начальным пробелам и не отпускает их . Затем (?!//)
проверяет, что все, что находится после ведущего пробела, не является маркером комментария, и, наконец, мы ищем foobar
в разрывах слов в любом месте строки.
(Если пробел был сопоставлен без притяжательного квалификатора, механизм регулярных выражений мог отступить от ведущего пробела и проверить наличие маркера комментария в неправильном месте, что привело к совпадению закомментированных строк.)
Данные испытаний:
$ cat file.txt
// foobar # do not match
foobar # 1st match
otherfoobar # do not match
something foobar # 2nd and final match
$ grep -P '^\s*+(?!//).*\bfoobar\b.*$' file.txt
foobar # 1st match
something foobar # 2nd and final match
foobar
, не найденное справа от //
, может быть выражено как:
^(?:(?!//).)*\bfoobar\b
Это последовательность из 0 или более(*
)символов (.
), каждый из которых не находится в начале последовательности //
((?!//)
), за которой следует символ foobar
, разделенный границами слов.