0

I have borrowed code from this link PHP regex templating - find all occurrences of {{var}} to implement a means of applying values to template fiies. This uses the preg_replace_callback() function

my preferred method of naming is name1.name2.name3=value, rather than name1_name2_name3=value, but the regex I am using seems to have a problem.

This one doesn't work.

template file

.aclass{
  font-width:{{newsflash.font.width}};
}

.ini values

newsflash.font.width=8px

regex used

'!\{\{(\w+).+\.\w+\}\}!'

output of print_r($matches)

Array
(
  [0] => {{newsflash.font.width}}
  [1] => newsflash
)

substitution is wrong because $matches[1] is wrong key key.

.aclass{
  font-width:;
}

I suspect there are libraries that already provide this functionality and would love to know about them, but I still want to know the fault with the regex.

The fullcode with the faulty regex is below.

$inputFileName = 'templateVars.css';
$outputFileName = 'templateVals.css';
$varsFileName = 'variables.ini';

$ini_array = parse_ini_file($varsFileName);
$matchesArray = array();

function replace_value($matches) {
  global $ini_array;
  global $matchesArray;
  print "<pre>";
  print_r($matches);
  print "</pre>";
  return $ini_array[$matches[1]];
}


$inputFileVar = file_get_contents($inputFileName);

print "<pre>";
print_r($ini_array);
print "</pre>";


print "<pre>";
print $inputFileVar;
print "</pre>";

$outFileVar = preg_replace_callback('!\{\{(\w+).+\.\w+\}\}!', 'replace_value', $inputFileVar);

print "<pre>";
print $outFileVar;
print "</pre>";

print "<pre>";
print $matchesArray;
print "</pre>";

Template to be matched

.aclass{
  font-width:{{newsflash.font.width}};
  color:{{newsflash.font.color}}
}

Contents of .ini file

newsflash.font.width=8px
newsflash.font.color=red
Community
  • 1
  • 1
  • 1
    The matches array appears to be correct... can you put up your replace callback call, and what you would desire the outcome be? – Lazy Bob Sep 12 '09 at 20:16

2 Answers2

1

the character . is not part of \w; and your .+ (outside the grouping parens) will match any nonempty string (. is wildcard). Therefore, $matches[1]=newsflash is correct.

What do you wnat the $matches[1] to be? This is not clear from your question, sorry.

mihi
  • 6,507
  • 1
  • 38
  • 48
  • I see your point, I want matches[1] to be newsflash.font.width, in english it should be either a word without dots, or a sequence of words with dots at the end followed by a word without a dot. –  Sep 12 '09 at 21:30
  • in that case, use `'!\{\{((?:\w+\.)*\w+)\}\}!'` as the regex if all the words should have at least one letter (i. e. it should not match `some..junk`). – mihi Sep 12 '09 at 21:35
  • in addition, you can omit the `?:` if you don't care about the existence of a matches[2] element. – mihi Sep 12 '09 at 21:38
  • You example worked perfectly. What is the signifance of the '?:' ? –  Sep 12 '09 at 21:46
  • `(?:...)` is just like (...) only that the parentheses will not create an element in the matches array (matches[2] in this case). The () are needed so that the * will repeat both the dot and the word. – mihi Sep 12 '09 at 22:01
0
!\{\{(\w[\.\w]*)\}\};?!

this regexp seems to matching your templates fine.

SilentGhost
  • 307,395
  • 66
  • 306
  • 293