On me donne deux variables, une chaîne [var str] et un tableau de mots [var exceptions]. Je remplace chaque caractère central de chaque mot de plus de 3 lettres par un astérisque en utilisant l'expression régulière suivante:

 var edited = str.replace(/\B\w\B/g, '*');

Par exemple, la chaîne "Ceci est un exemple de ce que je fais" serait renvoyée car "T ** s est un e ***** e de w ** t I suis d *** g ".

Cependant, je voudrais ajouter des exceptions à cette expression régulière. Ainsi, par exemple, on me donne le tableau (var exceptions = ["example","doing"]), alors je voudrais que l'expression régulière renvoie: "T ** s est un exemple de w ** t que je fais"

Est-ce que quelqu'un sait comment faire ça? S'il existe un moyen d'y parvenir en utilisant regex great, sinon je suis ouvert à d'autres suggestions.

Merci beaucoup :)

2
Johnny 9 août 2016 à 14:16

4 réponses

Meilleure réponse

Je transformerais probablement le tableau d'exclusions en une carte afin de bénéficier d'une vérification plus rapide si un mot est dans le tableau. Ensuite, j'utiliserais le fait que la fonction replace accepte une fonction pour le remplacement, et je prendrais la décision ici:

var exclude = ["example", "what"];
var str = "This is an example of what I am doing";

var map = Object.create(null);
exclude.forEach(function(entry) {
  map[entry] = true;
});
var edited = str.replace(/\b(\w)(\w+)(\w)\b/g, function(m, c0, c1, c2) {
  return map[m] ? m : c0 + "*".repeat(c1.length) + c2;
});
console.log(edited);

J'ai utilisé String#repeat dans ce qui précède, qui est de ES2015, mais peut être facilement modifié pour les navigateurs plus anciens. Ou utilisez c1.replace(/./g, "*") à la place.


Voici une version ES2015 +, utilisant Set plutôt qu'une carte d'objet:

let exclude = ["example", "what"];
let str = "This is an example of what I am doing";

let set = new Set();
exclude.forEach(entry => {
  set.add(entry);
});
let edited = str.replace(/\b(\w)(\w+)(\w)\b/g, (m, c0, c1, c2) =>
  set.has(m) ? m : c0 + "*".repeat(c1.length) + c2
);
console.log(edited);
1
T.J. Crowder 9 août 2016 à 11:33

Vous pouvez utiliser les mots d'exception - je vois qu'ils sont tous constitués de caractères de mot - comme groupe d'alternance et le capturer dans le groupe 1, puis les restaurer dans un rappel replace.

Le regex ressemblera à

/\b(example|doing)\b|\B\w\B/g

Voir la démo JS:

var exceptions = ["example","doing"];
var rx = new RegExp("\\b(" + exceptions.join("|") + ")\\b|\\B\\w\\B", "g");
var s = "This is an example of what I am doing";
var res = s.replace(rx, function ($0, $1) {
  return $1 ? $1 : '*';
});
console.log(res);

Détails du motif :

  • \b(example|doing)\b - faites correspondre un mot entier example ou doing et placez-le dans le groupe de capture n ° 1 pour être restauré dans le résultat plus tard
  • | - ou
  • \B\w\B - faire correspondre un caractère de mot à l'intérieur d'autres caractères de mot (de l'ensemble [a-zA-Z0-9_]).
2
Wiktor Stribiżew 9 août 2016 à 12:31

Vous pouvez le faire de cette façon, en supposant que les mots sont toujours séparés par des espaces exclusivement:

var str = "This is an example of what I am doing";
var exceptions = [ "example", "doing" ];

var edited = str.split(' ').map(function(w) {
  return exceptions.indexOf(w) != -1 ? w : w.replace(/\B\w\B/g, '*');
}).join(' ');

console.log(edited);
1
Arnauld 9 août 2016 à 11:31

Divisez la phrase en mots séparés avec .split(" "). Ensuite, pour chaque mot, vérifiez s'il se trouve dans le tableau des exceptions, s'il ne l'est pas, ajoutez-le simplement à newString sans modifications. Si ce n'est pas le cas, appliquez votre expression régulière.

 var newString = "";
 var exceptions = ["test"];
  "this is a test".split(" ").forEach(word =>{
       if(exceptions.includes(word))
         newString += word + " ";
       else
          newString += word.replace(/\B\w\B/g, '*') + " ";
   });

console.log(newString)
1
Dylan Meeus 9 août 2016 à 11:24