как вы указываете группы non-captureing в sed? - PullRequest
33 голосов
/ 28 января 2011

возможно ли указать группы без захвата в sed?

если да, то как?

Ответы [ 4 ]

28 голосов
/ 28 января 2011

Круглые скобки могут использоваться для группировки альтернатив. Например:

sed 's/a\(bc\|de\)f/X/'

говорит о необходимости заменить "abcf" или"adef" на "X", но скобки также захватывают. В sed нет возможности выполнять такую ​​группировку без захвата. Если у вас есть сложное регулярное выражение, которое выполняет захват альтернативной группировки и , вам просто нужно быть осторожным при выборе правильной группы захвата при замене.

Возможно, вы могли бы рассказать больше о том, чего вы пытаетесь достичь (в чем состоит ваша потребность в группах без захвата) и почему вы хотите избежать захвата групп.

Edit:

Существует тип скобок без захвата ((?:pattern)), которые являются частью Perl-совместимых регулярных выражений (PCRE). Они не поддерживаются в sed (но при использовании grep -P).

9 голосов
/ 11 апреля 2016

Ответ в том, что на момент написания вы не можете - sed не поддерживает это.Sed поддерживает BRE и ERE, но не PCRE.

(Примечание. В одном ответе указывается, что BRE также известен как POSIX sed, а ERE является расширением GNU через sed -r. Остается указать, что PCRE не поддерживается sed.)

Perl будет работать, для Windows или Linux

примеры здесь

https://superuser.com/questions/416419/perl-for-matching-with-regular-expressions-in-terminal

например, это от Cygwin в Windows

$ echo -e 'abcd' | perl -0777 -pe 's/(a)(?:b)(c)(d)/\1/s'
a

$ echo -e 'abcd' | perl -0777 -pe 's/(a)(?:b)(c)(d)/\2/s'
c

СуществуетПрограмма, пусть и для Windows, которая может выполнять поиск и замену в командной строке и поддерживает PCRE.Это называется rxrepl.Конечно, это не sed, но он выполняет поиск и замену на поддержку PCRE.

C:\blah\rxrepl>echo abc | rxrepl -s "(a)(b)(c)" -r "\1"
a

C:\blah\rxrepl>echo abc | rxrepl -s "(a)(b)(c)" -r "\3"
c

C:\blah\rxrepl>echo abc | rxrepl -s "(a)(b)(?:c)" -r "\3"
Invalid match group requested.

C:\blah\rxrepl>echo abc | rxrepl -s "(a)(?:b)(c)" -r "\2"
c

C:\blah\rxrepl>

Автор (не я) упомянул свою программу в ответе здесь https://superuser.com/questions/339118/regex-replace-from-command-line

У него действительно хороший синтаксис.

Стандартной вещью для использования будет Perl или почти любой другой язык программирования, который используют люди.

4 голосов
/ 28 января 2011

Я предполагаю, что вы говорите о синтаксисе backrefence, которые являются круглыми скобками ( ), а не скобками [ ]

По умолчанию sed будет интерпретировать ( ) буквально и не будет пытаться сделатьВозврат от них.Вам нужно экранировать их, чтобы сделать их особенными, как в \( \). Только когда вы используете опцию GNU sed -r, экранирование будет отменено.С sed -r, не экранированный ( ) будет создавать обратные ссылки, а экранированный \( \) будет считаться буквальным.Примеры для подражания:

POSIX sed

$ echo "foo(###)bar" | sed 's/foo(.*)bar/@@@@/'
@@@@

$ echo "foo(###)bar" | sed 's/foo(.*)bar/\1/'
sed: -e expression #1, char 16: invalid reference \1 on `s' command's RHS
-bash: echo: write error: Broken pipe

$ echo "foo(###)bar" | sed 's/foo\(.*\)bar/\1/'
(###)

GNU sed -r

$ echo "foo(###)bar" | sed -r 's/foo(.*)bar/@@@@/'
@@@@

$ echo "foo(###)bar" | sed -r 's/foo(.*)bar/\1/'
(###)

$ echo "foo(###)bar" | sed -r 's/foo\(.*\)bar/\1/'
sed: -e expression #1, char 18: invalid reference \1 on `s' command's RHS
-bash: echo: write error: Broken pipe

Обновление

Из комментариев:

Скобки без захвата только для групп ( ), поэтому вы можете использовать что-то вроде интервалов {n,m} без создания обратной ссылки \1 не существует.Во-первых, интервалы не являются частью POSIX sed, вы должны использовать расширение GNU -r, чтобы включить их.Как только вы включите -r, любые круглые скобки для групп будут также перехватываться для использования в качестве обратной ссылки.Примеры:

$ echo "123.456.789" | sed -r 's/([0-9]{3}\.){2}/###/'
###789

$ echo "123.456.789" | sed -r 's/([0-9]{3}\.){2}/###\1/'
###456.789
1 голос
/ 14 марта 2018

Как уже говорилось, невозможно иметь не захватывающие группы в sed.Это может быть очевидно, но не требующие захвата группы не являются необходимостью.Можно просто использовать желаемые захваты и игнорировать нежелательные, как если бы они не захватывали.Для справки, вложенные группы захвата нумеруются по порядку позиции "(".

Например,

echo "apple and bananas and monkeys" | sed -r "s/((apple|banana)s?)/\1x/g"

applex и банан s x и обезьян (примечание: "s" в бананах, первая большая группа)

против

echo "apple and bananas and monkeys" | sed -r "s/((apple|banana)s?)/\2x/g"

applex, бананакс и обезьяны (примечание: нет "s" в бананах, вторая меньшая группа)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...