2017-10-07 6 views
1

Je travaille sur des feuilles Excel très salissant, et d'essayer d'utiliser PHP pour trouver des indices ..PHP preg_replace: trouver une partie de chaîne ne commence pas par un point d'exclamation

J'ai une base de données MySQL avec toutes les formules à partir d'un excel document, et comme d'habitude, les noms de cellule de la feuille actuelle n'ont pas de "nom de feuille!" devant lui. Pour le rendre consultable (et trouver des routes mortes dans les formules) j'aime remplacer toutes les formules dans la base de données avec leur nom de feuille comme préfixe.

Exemple:

=+(sheet_factory_costs!A17/sheet_employees!D23)+T12+W12 

La base de données contient le nom de la feuille, et j'aime changer la formule ci-dessus avec cette sheetname (nous appelons de ce « sheet_turnover »).

=+(sheet_factory_costs!A17/sheet_employees!D23)+sheet_turnover!T12+sheet_turnover!W12 

J'essaie ceci en PHP avec preg_replace, et je pense que je dois les règles suivantes:

  1. Trouver une ou deux lettres, suivie directement par un numéro. C'est toujours une adresse de cellule dans les formules.
  2. Quand il y a un! sur la position avant, il y a déjà un nom de feuille. Donc, je cherche seulement les lettres et les chiffres ne commençant pas par un point d'exclamation.

Le problème semble être que le! est également un signe spécial dans les modèles. Même si je tente d'y échapper, il ne fonctionne pas:

$newformula = 
preg_replace('/(?<\!)[A-Z]{1,2}[0-9]/', 
'lala', 
$oldformula); 

(lala est mon marqueur temporaire pour voir si elle est la sélection des bonnes cellules-adresses)

(et oui, la lala est à seulement emplacements sur le premier numéro, mais ce n'est pas question en ce moment)

(et oui, tous Excel $ .. $ .. (permanents) marqueurs ont déjà été remplacés. pas besoin de construire que dans la formule)

+0

Vous devez doubler la barre oblique inverse car il a un sens échappant dans des chaînes, qui « manger » eux. – trincot

+0

En fait, '(? <\!)' Est une construction de regex invalide dans PCRE, si vous l'essayez, vous obtiendrez un avertissement sur une structure de groupe incomplet. Il ne s'agit pas du nombre de barres obliques inverses dont on a besoin ici. –

Répondre

0

Votre lookbehind négatif est corrompu, vous devez le définir comme (?<!!). Cependant, vous devez également utiliser soit une limite de mot avant, soit un (?<![A-Z]) lookbehind pour vous assurer que vous n'avez pas d'autres lettres avant le [A-Z]{1,2}.

Ainsi, vous pouvez utiliser

'~\b(?<!!)[A-Z]{1,2}[0-9]~' 

Voir la regex demo. Remplacez par sheet_turnover!$0$0 correspond à la valeur de correspondance.

Détails

  • \b - une limite de mot (il est nécessaire, ou name!AA11 serait encore s'apparié)
  • (?<!!) - pas ! immédiatement à gauche de l'emplacement actuel
  • [A-Z]{1,2} - 1 ou 2 lettres
  • [0-9] - un chiffre.

Une autre approche est correspondance et sauter « faux » contextes et correspondent et garder les « bons »:

'~\w+![A-Z]{1,2}[0-9](*SKIP)(*F)|\b[A-Z]{1,2}[0-9]~' 

Voir this regex demo.

Ici, \w+![A-Z]{1,2}[0-9](*SKIP)(*F)| partie correspond à 1 ou plusieurs caractères de texte, puis 1 ou 2 lettres ASCII en majuscules et puis un chiffre, et (*SKIP)(*F) omettra le match et le moteur sera procéder à la recherche de matchs après la fin du match précédent.

+0

Ce point d'exclamation doublé a fait l'affaire. Je ne comprends pas pourquoi je dois le faire de cette façon, mais ça fonctionne bien. Il n'y a pas de différence dans les résultats avec ou sans/b. Sans le/b il n'affecte pas le mot avant (le nom de la feuille): ancien: = + D16 + (P25/(O25 * (Entry_machines! C12))) nouveau: = + lala6 + (lala5/(lala5 * (Entry_machines ! C12))) –

+0

@TwomuchTime Je préfère que vous le traitiez comme un '!' Dans la construction '(?

+0

@TwomuchTime S'il y a deux lettres dans le nom de la colonne, '\ b' fera la différence. Essayez contre '+ D16 + (P25/(O25 * (Entry_machines! CC12)))' –