4 votes

Regex pour faire correspondre/remplacer les tabulations en tête sans lookbehind

J'essaie de faire correspondre chaque \t dans l'espace blanc de tête d'une ligne pour que je puisse les remplacer par deux espaces. Ceci est trivial avec un lookbehind non borné (c'est-à-dire de longueur variable).

text.replace(/(?<=^\s*)\t/gm, '  ')

Malheureusement, ce code s'exécute sur iOS, et pour une raison quelconque, Safari et iOS ont encore à mettre en œuvre les rétrospectives et encore moins des balises illimitées.

Je sais qu'il y a solutions de contournement pour les rétroviseurs mais je n'arrive pas à faire fonctionner celles que j'ai examinées.

Je préférerais ne pas capturer de caractères en dehors de chaque onglet, mais s'il n'y a pas d'autre moyen, je pourrais capturer les caractères autour des onglets dans des groupes de capture et ajouter $1 etc, à ma chaîne de remplacement.

Exemple de code de test

const text = `
\t\ta
  \t  b
 \t  \t c\td  \te
`

const expected = `
    a
      b
        c\td  \te
`

// throws error in iOS, which does not support lookbehinds
// const regex = /(?<=^\s*)\t/gm;
const regex = /to-do/gm;

const result = text.replace(regex, '  ')

console.log(`Text: ${text}`)
console.log(`Expected: ${expected}`)
console.log(`Result: ${result}`)
console.log(JSON.stringify([ expected, result ], null, 2))

if (result === expected) {
  console.info('Success! ')
} else {
  console.error('Failed ')
}

Mise à jour

Une solution moins qu'idéale serait d'utiliser deux regex et une fonction de remplacement.

const text = `
\t\ta
  \t  b
 \t  \t c\td  \te
`

const expected = `
    a
      b
        c\td  \te
`

const result = text.replace(/^\s*/gm, m => m.replace(/\t/g, '  '))

if (result === expected) {
  console.info('Success! ')
} else {
  console.error('Failed ')
}

Encore une fois, ce n'est pas l'idéal. Je suis un puriste.

1voto

anubhava Points 172509

Vous pouvez utiliser cette solution Javascript sans impliquer looknbehind :

const text = `
\t\ta
  \t  b
 \t  \t c\td  \te
`;

var repl = text.replace(/^[ \t]+/mg, g => g.replace(/\t/g, '  '));

console.log(repl);

0voto

Cary Swoveland Points 6784

Voici une solution Ruby, si un lecteur souhaite poster une solution Javascript basée sur celle-ci.

rgx = /[a-z].*|\t/
str.gsub(rgx) { |s| s[0] == "\t" ? '  ' : s }

donde str contient la chaîne de caractères qui doit être modifiée.

L'expression régulière est une alternance en deux parties :

[a-z]  # match a lower-case letter
.*     # match zero or more characters (to end of string)
|      # or
\t     # match a tab

Chaque correspondance est transmise au "bloc" ( { |s| ...} ) et est maintenu par la variable de bloc s . Si le premier caractère de la correspondance est une tabulation, deux espaces sont renvoyés ; sinon, le résultat est le même. s est renvoyé. Si [a-z].* est trouvée, il n'y aura pas d'autres correspondances car le reste de la chaîne (y compris éventuellement les tabulations) aura été consommé.

En Python, un lambda serait utilisé à la place du bloc de Ruby, comme suit

lambda m: '  ' if m.group()[0] == "\t" else m.group()

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X