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
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? Commented Sep 12, 2009 at 20:16

2 Answers 2

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.

Sign up to request clarification or add additional context in comments.

5 Comments

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.
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).
in addition, you can omit the ?: if you don't care about the existence of a matches[2] element.
You example worked perfectly. What is the signifance of the '?:' ?
(?:...) 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.
0
!\{\{(\w[\.\w]*)\}\};?!

this regexp seems to matching your templates fine.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.