Como usar [\ w] + na expressão regular em sed?

21

Estou no Windows, mas acho que minha pergunta ainda está bem colocada aqui.

C:\Users\User>grep --version
GNU grep 2.6.3

C:\Users\User>sed --version
GNU sed version 4.2.1

Eu notei que os seguintes trabalhos (outputting here ):

echo here | grep -E "\w+"
echo here | grep -E "[her]+"

Mas isso não funciona (não produz nada):

echo here | grep -E "[\w]+"

Isso novamente faz (produzindo here ):

echo here | grep -P "[\w]+"

Então [\w] é algo específico para expressões regulares Perl, eu suponho. Isso está correto?

Então, vamos falar em sed . Isso funciona (produzindo gone ):

echo here | sed -r "s/\w+/gone/"
echo here | sed -r "s/[her]+/gone/"

E mais uma vez, isso não acontece (outputting here ):

echo here | sed -r "s/[\w]+/gone/"

Agora, como posso ativar expressões regulares Perl para sed? Existe alguma maneira?

    
por bers 08.05.2015 / 15:55

3 respostas

10

Diferentes ferramentas e versões suportam diferentes variantes de expressões regulares. A documentação de cada um lhe dirá o que eles suportam.

Existem padrões para que se possa confiar em um conjunto mínimo de recursos disponíveis em todos os aplicativos em conformidade.

Por exemplo, todas as implementações modernas de sed e grep implementam expressões regulares básicas como especificado pelo POSIX (pelo menos uma versão ou outra do padrão, mas esse padrão não evoluiu muito nesse aspecto no últimas décadas).

No POSIX BRE e ERE, você tem a classe de caractere [:alnum:] . Isso corresponde a letras e dígitos em sua localidade (observe que geralmente inclui muito mais do que a-zA-Z0-9 , a menos que a localidade seja C).

Então:

grep -x '[[:alnum:]_]\{1,\}'

corresponde a um ou mais alnums ou _.

[\w] é exigido pelo POSIX para corresponder à barra invertida ou w . Portanto, você não encontrará uma implementação de grep ou sed onde estiver disponível (a menos que seja por meio de opções não padrão).

O comportamento para \w sozinho não é especificado por POSIX, portanto, as implementações podem fazer o que quiserem. O GNU grep adicionou isso há muito tempo.

O

GNU grep costumava ter seu próprio mecanismo regexp, mas agora ele usa o GNU libc (apesar de incorporar sua própria cópia).

Pretende corresponder aos alnums e sublinhados na sua região. No entanto, atualmente ele tem um bug, pois ele só corresponde a caracteres de byte único (por exemplo, não é em uma localidade UTF-8, embora seja claramente uma letra e mesmo que seja compatível em todas as localidades onde é um único personagem).

Existe também um operador \w regexp no regexp perl e no PCRE. PCRE / perl não são expressões regulares POSIX, são apenas outra coisa.

Agora, com a forma como o GNU grep -P usa o PCRE, ele tem o mesmo problema de sem -P . Ele pode ser trabalhado por lá usando (*UCP) (embora isso também tenha efeitos colaterais em locais não UTF8).

O GNU sed também usa os regexs do GNU libc para seus próprios regexps. Ele o utiliza de tal forma que não tem o mesmo erro que o GNU grep .

O GNU sed não suporta os PCREs. Há alguma evidência no código que foi tentada antes, mas não parece mais estar na agenda.

Se você quiser as expressões regulares do Perl, use apenas perl .

Caso contrário, diria que, em vez de confiar em um recurso não padrão falso de sua implementação específica de sed / grep , seria melhor manter o padrão e usar [_[:alnum:]] .

    
por 08.05.2015 / 16:45
6

Você está correto - \w faz parte das expressões regulares compatíveis com PCRE - perl. Não faz parte da regex 'padrão'. link

Algumas versões do sed podem suportá-lo, mas eu sugiro que a maneira mais fácil é usar apenas perl no modo sed , especificando o sinal -p . (Junto com o -e ). (Mais detalhes em perlrun )

Mas você não precisa de [] nesse exemplo - isso é para grupos de material válido.

echo here  | perl -pe 's/\w+/gone/'

Ou no Windows:

C:\>echo here  | perl -pe "s/\w+/gone/"
gone
C:\>echo here  | perl -pe "s/[\w\/]+/gone/"
gone

Veja perlre para mais coisas sobre o PCRE.

Você pode obter o perl aqui: link

    
por 08.05.2015 / 16:25
1

Eu suspeito que grep e sed estejam decidindo de forma diferente quando aplicar o [] e quando expandir o \w . Em perl regex \w significa qualquer caractere de palavra e [] define um grupo para aplicar qualquer um dos caracteres como uma correspondência. Se você "expandir" o \w antes do [] , será uma classe de caractere de todos os caracteres da palavra. Se, em vez disso, você usar [] primeiro, você terá uma classe de caractere com dois caracteres \ e w , para corresponder a qualquer padrão que contenha um ou mais desses dois caracteres.

Portanto, parece que sed está vendo o [] e tratando-o como contendo os caracteres exatos a serem correspondidos, em vez de respeitar a sequência especial \w as perl e grep do. Naturalmente, o [] é completamente desnecessário neste exemplo, mas talvez se possa imaginar casos em que isso seria importante, mas então você poderia fazê-lo funcionar com parênteses e ors.

    
por 08.05.2015 / 16:34