J'ai un fichier texte qui a des modèles comme:
-a z -b z -c z -d z
Je voudrais remplacer tous les mots ne commençant pas par - par z code >. Donc, le texte attendu est
-a a -b b -c c -d d
J'ai essayé % s /^(-\(.*\))/ z / g mais cela semble tout remplacer.
3 Réponses :
Le premier problème ici est la gourmandise de * (voir : h / star , qui dit Correspond à 0 ou plus de l'atome précédent, autant que possible. ).
La question indique que seuls les mots doivent être remplacés, nous utilisons donc le mot atom \ w . Nous ne pouvons pas utiliser
qqnW.q
car le [^ -] correspond à un caractère, y compris les espaces, et casse des choses.
Nous pensons que nous avons besoin d'une analyse négative à la place:
" these should be typed in normal mode /-\w\+<ENTER> W ciwz<ESC>
Maintenant, le problème est que aaa dans -aaa correspond: le premier a n'est pas un - , donc vim dit joyeusement c'est une correspondance .
Nous allons donc faire des non-regex.
L'idée est de rechercher - \ w \ + , puis de passer au mot suivant et de faire le changement ( Ceci est fortement basé sur le modèle d'entrée):
" don't use this either :%substitute/-\@!\w\+/z/g
Après avoir tapé ces derniers, vous pouvez terminer le fichier entier avec nW. , mais c'est au moins un caractère de plus que je ne veux taper, et je déteste parfois la touche Maj. Nous le transformons donc en macro:
" don't use :%substitute/[^-]\w\+/z/g
Et rejouons autant de fois que vous le souhaitez avec l'un des
@q @@ (après avoir exécuté @q au moins une fois) 100 @ q (nous voulons choisir un grand nombre pour couvrir tout le fichier) J'ai omis les parenthèses inutiles de l'expression régulière d'origine. J'ai également omis le ^ car, parmi les exemples donnés, tout le texte à remplacer ne se trouve pas au début de la ligne. Voir : h / ^ . Enfin, j'ai changé * en \ + afin que nous ne comparions que si, en fait, il y a des caractères de mots pour commencer.
Merci pour l'aide! C'est ce que j'en suis le plus proche. Cependant, cela semble remplacer les mots qui commencent par -. Le résultat ici est donc z a z b z c z d. Je voudrais remplacer les mots qui ne commencent pas par - pour obtenir -a z -b z -c z -d d.
Salut, Pourquoi cela ne fonctionnerait-il pas s'il y a plusieurs caractères après -? Par exemple: -abcd abcd -bcd bcd -cd cd -d d. Je pensais que le w + s'occuperait de cela. Désolé pour les questions de suivi, j'essaie de comprendre cela depuis un certain temps maintenant.
@GargiSharma ça devrait vraiment marcher, c'est étrange ... je peux tester plus tard ce soir et voir
@GargiSharma plus de mises à jour: les problèmes de regex défient malheureusement l'intuition dans certains cas. Le [^ -] correspondait à des endroits incorrects, et essayer de le réparer avec un regard négatif en arrière ne faisait que le rendre plus faux. C'était donc le plus proche que je pouvais obtenir. Si l'entrée est radicalement différente de -word word , cela peut ne pas fonctionner
Merci d'aider @D. Ben Knoble!
Une solution possible en utilisant : s serait:
:s/\(^\|\s\)\zs[^- \t]\S*/z/g
Cela commence par faire correspondre le début de la ligne avec ^ , ou un espace blanc avec \ s , en utilisant un \ | pour faire correspondre l'un ou l'autre et en utilisant \ ( et \) pour faire correspondre cela en tant que groupe ( pour empêcher ^ de correspondre tout seul.)
Ensuite, nous utilisons \ zs pour marquer le début du match que nous capturerons. Nous avons donc trouvé un espace, mais nous ne le remplaçons pas vraiment, seulement ce qui suit.
Ensuite, nous utilisons [^ - \ t] , qui est une collection utilise ^ pour faire correspondre tout caractère autre que - , un espace ou un caractère de tabulation \ t (la fin de ligne ne correspondra pas non plus.) (Une alternative ici est d'utiliser [^ - [: space:]] code>, qui utilise le [: space:] classe de caractères.)
Ensuite, nous faisons correspondre zéro ou plusieurs caractères non espace avec \ S * . La répétition avec * est gourmande, donc ça va correspond à la plus longue séquence de non-blancs.
Le résultat final est que vous faites correspondre des séquences complètes de caractères non-blancs (mots) et uniquement celles qui ne commencent pas par - . Faire correspondre explicitement les espaces ou le début de ligne permet de garantir que le début des mots est correctement ancré.
Ouais, nous avions besoin de limites WORD en fait! 😁 La correspondance \ < vient close, mais malheureusement, il correspond à la limite basée sur 'iskeyword' code > , dont l'OMI n'est pas exactement ce dont nous avons besoin ici ... L'ajustement de 'iskeyword' pourrait faire fonctionner cela, mais je pense que c'est un peu fragile, même si cela peut être fait pour fonctionner ... \ zs à la rescousse!
J'ai essayé cette approche: remplacez l'espace plus la lettre par l'espace z
:%s, [a-z], z,g