Je veux faire correspondre un motif non gourmand (expression régulière) awk
. Voici un exemple:
echo "@article{gjn, Author = {Grzegorz J. Nalepa}, " | awk '{ sub(/@.*,/,""); print }'
Est-il possible d'écrire une expression régulière qui sélectionne la chaîne la plus courte?
@article{gjn,
au lieu de cette longue chaîne?:
@article{gjn, Author = {Grzegorz J. Nalepa},
Je veux obtenir ce résultat:
Author = {Grzegorz J. Nalepa},
J'ai un autre exemple:
echo " , article {gjn, Auteur = {Grzegorz J. Nalepa}," | awk '{sub (/ , [^,] *, /, ""); impression }' ↑ ↑ ^^^^^
Notez que j'ai changé les @
caractères en caractères virgule ( ,
) à la première position de la chaîne d'entrée et de l'expression régulière (et également changé .*
en [^,]*
). Est-il possible d'écrire une expression régulière qui sélectionne la chaîne la plus courte?
, Author = {Grzegorz J. Nalepa},
au lieu de la chaîne plus longue?:
,article{gjn, Author = {Grzegorz J. Nalepa},
Je veux obtenir ce résultat:
,article{gjn
awk
regular-expression
nowy1
la source
la source
Author
suivre une virgule et un espace, suivi d'un espace suivi par=
suivi d'un espace suivi{
par tout autre non}
suivi}
, bien que cela nécessite (entre autres) que vous ne puissiez pas imbriquer{}
à l'intérieur de la= { ... }
pièce.Réponses:
Si vous souhaitez sélectionner
@
et jusqu'au premier,
après cela, vous devez le spécifier comme@[^,]*,
Ceci est
@
suivi d'un nombre quelconque (*
) de non-virgules ([^,]
) suivi d'une virgule (,
).Cette approche fonctionne comme l'équivalent
@.*?,
, mais pas pour des choses comme@.*?string
, c'est là que ce qui est après est plus qu'un seul caractère. Nier un personnage est facile, mais nier les chaînes dans les expressions régulières est beaucoup plus difficile .Une approche différente consiste à prétraiter votre entrée pour remplacer ou ajouter le préfixe
string
à un caractère qui autrement n'apparaît pas dans votre entrée:Si vous ne pouvez pas garantir que l'entrée ne contiendra pas votre caractère de remplacement (
\1
ci-dessus), une approche consiste à utiliser un mécanisme d'échappement:Cela fonctionne pour les
string
s fixes mais pas pour les expressions rationnelles arbitraires comme pour l'équivalent de@.*?foo.bar
.la source
Il existe déjà plusieurs bonnes réponses fournissant des solutions pour
awk
l'incapacité de faire des correspondances non gourmandes, donc je fournis quelques informations sur une autre façon de le faire en utilisant des expressions régulières compatibles Perl (PCRE). Notez que la plupart desawk
scripts simples "match and print" peuvent facilement être réimplémentés enperl
utilisant l'-n
option de ligne de commande, et des scripts plus complexes peuvent être convertis avec le traducteur a2p Awk to Perl.Perl a un opérateur non gourmand qui peut être utilisé dans les scripts Perl et tout ce qui utilise PCRE. Par exemple, également implémenté dans l'
-P
option GNU grep .PCRE n'est pas identique aux expressions régulières de Perl, mais il est très proche. C'est un choix populaire d'une bibliothèque d'expressions régulières pour de nombreux programmes, car elle est très rapide, et les améliorations Perl des expressions régulières étendues sont très utiles.
Depuis la page de manuel perlre (1) :
la source
Il s'agit d'un ancien article, mais les informations suivantes peuvent être utiles pour les autres.
Il existe un moyen, certes grossier, d'effectuer une correspondance RE non gourmande dans awk. L'idée de base est d'utiliser la fonction match (chaîne, RE) et de réduire progressivement la taille de la chaîne jusqu'à ce que la correspondance échoue, quelque chose comme (non testé):
la source
Pour les expressions générales, cela peut être utilisé comme une correspondance non gourmande:
J'utilise ceci basé sur la réponse de @ JimMellander.
smatch
se comporte commematch
, en retournant:la source
Il n'y a aucun moyen dans awk de faire une correspondance non gourmande. Cependant, vous pourrez peut-être obtenir la sortie souhaitée. La suggestion de sch fonctionnera pour cette ligne. Si vous ne pouvez pas compter sur une virgule, mais que "Author" est toujours le début de ce que vous voulez, vous pouvez le faire:
Si le nombre de caractères précédant Auteur est toujours le même, vous pouvez le faire:
Vous avez juste besoin de savoir à quoi ressemblent vos données sur l'ensemble.
la source
Il y a toujours un moyen. Le problème donné peut être résolu assez facilement en utilisant des virgules comme séparateur.
Lorsque le nombre de champs varie, quelque chose de légèrement meilleur est généralement nécessaire. Dans ce cas, trouver un mot d'arrêt est souvent payant, car vous pouvez couper quoi que ce soit de la ligne en les utilisant. Dans le contexte de l'exemple, voici ce que j'entends par mots vides.
la source
Je sais que c'est un ancien poste. Mais voici quelque chose qui utilise simplement awk comme OP comme demandé:
A = @ article {gjn2010jucs, Author = {Grzegorz J. Nalepa},
echo $ A | awk 'sub (/ @ [^,] * /, "")'
Sortie:,
Auteur = {Grzegorz J. Nalepa},
la source