Referência retroativa no regex Awk

Referência retroativa no regex Awk

É possível fazer isso no Awk?:

echo "eoe" | sed -nr '/^(.*)o\1$/p'

Responder1

Não está no padrão awk(o POSIX awkusa EREs POSIX que não suportam referências anteriores e \1significa o caractere 0x1 no awk, emboraexistem algumas ambigüidades). É possível busybox awkusar:

busybox awk '$0 ~ "^(.*)o\\1$"'

(o que isso pode ou não fazer (se "\\1"deve corresponder a um literal \1ou ao caractere 0x1 ou não ser especificado) énão está claro na especificação POSIX. Na minha leitura, parece implicar que deve corresponder a um caractere 0x1, mas isso não acontece /usr/xpg4/bin/shno Solaris 11, por exemplo, que é um sistema operacional certificado (onde corresponde literalmente \1))

Com any awk, para esse regexp específico, você poderia adotar outra abordagem como:

awk 'length % 2 && \
       substr($0, (length+1)/2, 1) == "o" && \
       substr($0, 1, (length-1)/2) == substr($0, (length+3)/2)'

Conforme mencionado acima, os EREs POSIX não suportam referências anteriores. GNU sedusa -rEREs, mas são GNU EREs que suportam referências anteriores como uma extensão do padrão. O que isso significa é que

grep -Ex '(.*)o\1'

(ou o mesmo com egrep) não é portátil. No entanto:

grep -x '\(.*\)o\1'

é POSIX e portátil. BREs POSIX suportam referências anteriores, assim como implementações históricas de grep. perlregexps ou PCREs também suportam referências anteriores, então você pode fazer:

perl -lne 'print if /^(.*)o\1$/'

informação relacionada