Quiero hacer coincidir patrones no codiciosos (expresiones regulares) awk
. Aquí hay un ejemplo:
echo "@article{gjn, Author = {Grzegorz J. Nalepa}, " | awk '{ sub(/@.*,/,""); print }'
¿Es posible escribir una expresión regular que seleccione la cadena más corta?
@article{gjn,
en lugar de esta larga cuerda ?:
@article{gjn, Author = {Grzegorz J. Nalepa},
Quiero obtener este resultado:
Author = {Grzegorz J. Nalepa},
Tengo otro ejemplo:
echo " , artículo {gjn, Autor = {Grzegorz J. Nalepa}," | awk '{sub (/ , [^,] *, /, ""); impresión }' ↑ ↑ ^^^^^
Tenga en cuenta que cambié los @
caracteres a comas ( ,
) en la primera posición de la cadena de entrada y la expresión regular (y también cambié .*
a [^,]*
). ¿Es posible escribir una expresión regular que seleccione la cadena más corta?
, Author = {Grzegorz J. Nalepa},
en lugar de la cadena más larga ?:
,article{gjn, Author = {Grzegorz J. Nalepa},
Quiero obtener este resultado:
,article{gjn
awk
regular-expression
nowy1
fuente
fuente
Author
seguir una coma y un espacio en blanco, seguido de un espacio en blanco seguido de=
un espacio en blanco seguido{
de cualquier no}
seguido}
, aunque esto requiere (entre otras cosas) que no pueda anidar{}
dentro de la= { ... }
pieza.Respuestas:
Si desea seleccionar
@
y hasta el primero,
después de eso, debe especificarlo como@[^,]*,
Esto es
@
seguido por cualquier número (*
) de no comas ([^,]
) seguido de una coma (,
).Ese enfoque funciona como el equivalente de
@.*?,
, pero no para cosas como@.*?string
, ahí es donde lo que está después es más que un solo personaje. Negar un personaje es fácil, pero negar cadenas en expresiones regulares es mucho más difícil .Un enfoque diferente es preprocesar su entrada para reemplazar o anteponer el
string
con un carácter que de otra manera no ocurriría en su entrada:Si no puede garantizar que la entrada no contendrá su carácter de reemplazo (
\1
arriba), un enfoque es utilizar un mecanismo de escape:Eso funciona para
string
s fijas pero no para expresiones regulares arbitrarias como para el equivalente de@.*?foo.bar
.fuente
Ya hay varias buenas respuestas que brindan soluciones para
awk
la incapacidad de hacer coincidencias no codiciosas, por lo que proporciono información sobre una forma alternativa de hacerlo utilizando Expresiones regulares compatibles con Perl (PCRE). Tenga en cuenta que lasawk
secuencias de comandos más simples de "coincidencia e impresión" se pueden volver a implementar fácilmenteperl
con la-n
opción de línea de comandos, y las secuencias de comandos más complejas se pueden convertir con traductor Awk to Perl de a2p .Perl tiene un operador no codicioso que puede usarse en scripts de Perl y cualquier cosa que use PCRE. Por ejemplo, también implementado en la
-P
opción GNU grep .PCRE no es idéntico a las expresiones regulares de Perl, pero está muy cerca. Es una opción popular de una biblioteca de expresiones regulares para muchos programas, porque es muy rápida y las mejoras de Perl para expresiones regulares extendidas son muy útiles.
Desde la página del comando man perlre (1) :
fuente
Esta es una publicación antigua, pero la siguiente información puede ser útil para otros.
Hay una manera, ciertamente cruda, de realizar una correspondencia RE no codiciosa en awk. La idea básica es utilizar la función de coincidencia (cadena, RE) y reducir progresivamente el tamaño de la cadena hasta que la coincidencia falle, algo así como (no probado):
fuente
Para expresiones generales, esto se puede usar como una coincidencia no codiciosa:
Estoy usando esto basado en la respuesta de @ JimMellander.
smatch
se comporta comomatch
, volviendo:fuente
En awk no hay forma de hacer correspondencias no codiciosas. Sin embargo, es posible que pueda obtener la salida deseada. La sugerencia de sch funcionará para esa línea. Si no puede confiar en una coma, pero "Autor" es siempre el comienzo de lo que desea, puede hacer esto:
Si el número de caracteres que precede al Autor es siempre el mismo, puede hacer esto:
Solo necesita saber cómo se ven sus datos en todo el conjunto.
fuente
Siempre hay una manera. El problema dado se puede resolver con bastante facilidad utilizando comas como separador.
Cuando el número de campos varía, generalmente se necesita algo ligeramente mejor. En tal caso, encontrar palabras de detención a menudo vale la pena, ya que puede cortar cualquier cosa de la línea al usarlas. En el contexto del ejemplo, esto es lo que quiero decir con palabras vacías.
fuente
Sé que esta es una publicación anterior. Pero aquí hay algo simplemente usando awk como OP según lo solicitado:
A = @ article {gjn2010jucs, Author = {Grzegorz J. Nalepa},
echo $ A | awk 'sub (/ @ [^,] * /, "")'
Salida:
Autor = {Grzegorz J. Nalepa},
fuente