Eu quero fazer correspondência não padrão ganancioso (expressão regular) awk
. Aqui está um exemplo:
echo "@article{gjn, Author = {Grzegorz J. Nalepa}, " | awk '{ sub(/@.*,/,""); print }'
É possível escrever uma expressão regular que selecione a string mais curta?
@article{gjn,
em vez desta longa string ?:
@article{gjn, Author = {Grzegorz J. Nalepa},
Eu quero obter este resultado:
Author = {Grzegorz J. Nalepa},
Eu tenho outro exemplo:
eco " , artigo {gjn, Autor = {Grzegorz J. Nalepa}," | awk '{sub (/ , [^,] *, /, ""); impressão }' ↑ ↑ ^^^^^
Observe que mudei os @
caracteres para vírgula ( ,
) na primeira posição da sequência de entrada e da expressão regular (e também mudei .*
para [^,]*
). É possível escrever uma expressão regular que selecione a string mais curta?
, Author = {Grzegorz J. Nalepa},
em vez da string mais longa ?:
,article{gjn, Author = {Grzegorz J. Nalepa},
Eu quero obter este resultado:
,article{gjn
awk
regular-expression
nowy1
fonte
fonte
Author
vírgula e espaço em branco, seguido por espaço em branco seguido por=
espaço em branco seguido{
por qualquer não-}
seguido por}
, embora isso exija (entre outras coisas) que você não possa aninhar{}
dentro da= { ... }
peça.Respostas:
Se você deseja selecionar
@
e até o primeiro,
depois disso, especifique-o como@[^,]*,
Isso é
@
seguido por qualquer número (*
) de não vírgulas ([^,]
) seguido de uma vírgula (,
).Essa abordagem funciona como o equivalente
@.*?,
, mas não para coisas como@.*?string
, é aí que o que está depois é mais do que um único personagem. Negar um personagem é fácil, mas negar seqüências de caracteres em regexps é muito mais difícil .Uma abordagem diferente é pré-processar sua entrada para substituir ou adicionar
string
um caractere que, de outra forma, não ocorre em sua entrada:Se você não pode garantir que a entrada não contenha seu caractere de substituição (
\1
acima), uma abordagem é usar um mecanismo de escape:Isso funciona para
string
s fixos, mas não para regexps arbitrários, como para o equivalente a@.*?foo.bar
.fonte
Já existem várias boas respostas que fornecem soluções
awk
alternativas para a incapacidade de fazer correspondências não gananciosas, por isso estou fornecendo algumas informações sobre uma maneira alternativa de fazê-lo usando PCRE ( Expressões Regulares Compatíveis com Perl ). Observe que a maioria dosawk
scripts simples "combinar e imprimir" pode ser facilmente reimplementadaperl
usando a-n
opção de linha de comando, e scripts mais complexos podem ser convertidos com o conversor a2p Awk para Perl.O Perl possui um operador não ganancioso que pode ser usado em scripts Perl e qualquer coisa que use o PCRE. Por exemplo, também implementado na
-P
opção do GNU grep .PCRE não é idêntico às expressões regulares do Perl, mas é muito próximo. É uma escolha popular de uma biblioteca de expressões regulares para muitos programas, porque é muito rápida e os aprimoramentos do Perl para expressões regulares estendidas são muito úteis.
De página do manual perlre (1) :
fonte
Esta é uma postagem antiga, mas as informações a seguir podem ser úteis para outras pessoas.
Existe uma maneira, reconhecidamente grosseira, de executar uma correspondência RE não gananciosa no awk. A idéia básica é usar a função match (string, RE) e reduzir progressivamente o tamanho da string até que a correspondência falhe, algo como (não testado):
fonte
Para expressões gerais, isso pode ser usado como uma correspondência não gananciosa:
Estou usando isso com base na resposta do @ JimMellander.
smatch
se comporta comomatch
, retornando:fonte
Não existe uma maneira no awk de fazer combinações não gananciosas. Você pode conseguir a saída desejada, no entanto. a sugestão de sch funcionará para essa linha. Se você não pode confiar em uma vírgula, mas "Autor" é sempre o início do que você deseja, você pode fazer o seguinte:
Se o número de caracteres que precede o Autor for sempre o mesmo, você poderá fazer o seguinte:
Você só precisa saber como são os seus dados em todo o conjunto.
fonte
Há sempre uma maneira. O problema em questão pode ser resolvido facilmente usando vírgulas como separador.
Quando o número de campos varia, geralmente é necessário algo um pouco melhor. Nesse caso, encontrar palavras de parada geralmente compensa, pois você pode cortar qualquer coisa da linha usando-as. Dentro do contexto do exemplo, aqui está o que quero dizer com palavras de parada.
fonte
Eu sei que este é um post antigo. Mas aqui está algo usando o awk como OP, conforme solicitado:
A = @ article {gjn2010jucs, Autor = {Grzegorz J. Nalepa},
echo $ A | awk 'sub (/ @ [^,] * /, "")'
Saída
:, Autor = {Grzegorz J. Nalepa},
fonte