Rechercher et remplacer à laide dexpressions régulières

Jai un fichier avec un certain nombre de paramètres par défaut de lutilisateur. Je souhaite modifier une partie du texte, mais jai du mal proposer un correcteur et un remplaçant. En utilisant lexemple suivant:

############################################################################### # Trackpad, mouse, keyboard, Bluetooth accessories, and input # ############################################################################### # Trackpad: enable tap to click for this user and for the login screen defaults write com.apple.driver.AppleBluetoothMultitouch.trackpad Clicking -bool true 

Je « voudrais remplacer # Trackpad: ... avec running "Trackpad: ..."

Pour résumer le problème, jai trouvé quelque chose en utilisant un testeur dexpression régulière:

/\n\n#\s(.*)/g 

Si jessaie dutiliser ceci dans Vim, cela ne fonctionne pas pour moi:

:/\n\n#\s(.*)/running "\1"/g 

Je suppose que mon problème se résume à deux questions spécifiques:

  1. Comment puis-je éviter de rechercher des caractères \n, et plutôt massurer que # napparaît pas à la fin du groupe de recherche?
  2. Comment puis-je utiliser efficacement les groupes de capture?

Voici quelques bonnes réponses. Difficile de choisir entre les trois, mais je pense que la réponse choisie est la plus précise pour mes spécifications dorigine. Je vous recommande dessayer les trois réponses avec le fichier réel pour voir ce que vous en pensez.

Réponse

Pour être clair… Je crois que vous avez demandé que ce soit le résultat de la substitution?

############################################################################### # Trackpad, mouse, keyboard, Bluetooth accessories, and input # ############################################################################### running "Trackpad: enable tap to click for this user and for the login screen" defaults write com.apple.driver.AppleBluetoothMultitouch.trackpad Clicking -bool true 

Dans ce cas, je recommande la commande suivante:

:%s/\n\n#\s\+\(.*\)/^M^Mrunning "\1"/

Explication du modèle

:s/PATTERN/REPLACEMENT/ est la commande substitute . Le signe de pourcentage :%s le fait fonctionner sur lensemble du fichier, plutôt que sur la ligne courante.

Le \n\n indique que la ligne dintérêt doit apparaître après une ligne vierge. Si vous ne vous souciez pas de la ligne vide précédente, alors ^ suffirait.

#\s\+ correspond à un hachage caractère suivi dun ou plusieurs espaces blancs. \(.*\) capture tout le texte suivant sur la ligne.

Explication du texte de remplacement

^M^M insère deux extrémités de lignes pour remplacer les \n\n qui étaient présents dans le modèle. Sinon, le texte serait déplacé à la fin de la ligne précédant la ligne vide. Pour saisir chaque ^M, appuyez sur Ctrl-V Ctrl-M .

Ensuite, insérez la chaîne running, suivie de ce qui a été capturé entre parenthèses entre guillemets.

Commentaires

  • Je ne peux pas modifier votre réponse, mais je pense que vous vouliez dire :%s/\v\n\n#\s+(.*)/^M^Mrunning "\1"/ (ajouté la  » magie « ). Il est vraiment difficile de choisir une réponse correcte à ma question initiale, mais jestime que cette réponse est la plus proche de ma réponse attendue initiale. Cest aussi le seul qui fonctionne dans tout le fichier sans quil soit nécessaire de sélectionner une plage.
  • IIRC vous pouvez utiliser \r au lieu de ^M pour obtenir de nouvelles lignes?

Réponse

Jutiliserais quelque chose comme:

:s/^#\s\+\(.\{-}\):/running "\1":/ 
  • ^# pour correspondre au caractère # ancré au début de la ligne (cela répond à la question 1)
  • \s\+ pour faire correspondre nimporte quel espace une ou plusieurs fois
  • \( pour démarrer un groupe (ceci répond à la question 2)
  • .\{-}\ pour correspondre à nimporte quel caractère 0 fois ou plus dans un manière non gourmande ; ceci est différent de .* en ce quil essaie de correspondre le moins possible, et pas autant que possible. Essayez dajouter un caractère : dans le commentaire pour voir pourquoi cela est important
  • \) pour mettre fin au sous-groupe.
  • : correspond à un littéral :

Nous le remplaçons ensuite par le texte que vous voulez et utilisez \1 pour faire référence au groupe que nous avons capturé.

Jai trouvé quelque chose en utilisant un testeur de regex

La syntaxe des expressions régulières est un peu comme la syntaxe wiki: il y en a beaucoup, elles se ressemblent toutes en un coup dœil, aucune est évidemment meilleur que tout autre, mais il existe de nombreuses différences.

Aujourdhui, les expressions régulières dites « compatibles Perl » sont de facto la valeur par défaut dans la plupart des langages, mais les expressions régulières Vim ne le sont pas compatible avec les expressions compatibles Perl! La syntaxe des expressions rationnelles Vim remonte au moins aux « 70 », quand Perl nétait même pas là.

Vous pouvez voir cela avec les sous-groupes, où vous devez utiliser \( et non ( (ceci est compatible avec la syntaxe POSIX « basique », mais pas avec la syntaxe POSIX « étendue » ou la syntaxe Perl plus courante).Vous pouvez contrôler cela en ajoutant lindicateur \v dans un modèle (voir :help /\v pour plus de détails), cela le rendra « plus compatible », mais pas complètement (vous devez toujours utiliser .{-} pour les correspondances non gourmandes par exemple)

Cela pourrait donc expliquer pourquoi utiliser « un testeur dexpression régulière » fonctionne presque, mais pas tout à fait.

http://www.vimregex.com/ comme un bon aperçu / aide-mémoire des expressions régulières Vim.

Commentaires

  • Excellente réponse, surtout avec pourquoi regex! = regex. Quant à votre recherche et remplacement, ‘ est un peu délicat car le commentaire peut ou non avoir un :. Voir le fichier complet pour plus de détails github.com/squarefrog/dotfiles/blob/master/osx/…

Réponse

Vous pouvez:

  • rechercher des lignes qui ne se terminent pas dans #: :/[^#]$/
  • remplacer #\s(.*) au début de la ligne: s/\v^#\s(.*)/running "\1"/

Pour utiliser des groupes, vous devez soit:

  • échapper les crochets afin que ils font partie de la syntaxe regex: \(.*\), ou
  • utilisent « magic » par commençant lexpression par \v: s/\v...

Combinaison:

:/[^#]$/s/\v^#\s(.*)/running "\1"/ 

Commentaires

  • Cela fonctionne à merveille, merci davoir inclus une explication de ce que signifient les balises plutôt que juste le texte dont javais besoin écrivez.
  • Merci davoir précisé que les crochets ont t o être échappé afin de faire partie de la syntaxe regex. Jai toujours eu un problème avec les groupes dexpression régulière pour les faire fonctionner.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *