views:

48

answers:

2

I have borrowed code from this link http://stackoverflow.com/questions/959017/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  A: 

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
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`).
mihi
in addition, you can omit the `?:` if you don't care about the existence of a matches[2] element.
mihi
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.
mihi
A: 
!\{\{(\w[\.\w]*)\}\};?!

this regexp seems to matching your templates fine.

SilentGhost