开发者

PHP Simple Regex

I need to change something like this:

' . $scripturl . ' '.$scripturl.' ' .$scripturl .' '.$context['forum_name'].'

Basically, the amount of spaces in between the ' and . and $ shouldn't matter, it needs to grab it all beginning from the ' and replace it with either {$scripturl} or {$context[forum_name]}

Also, it should do this (with curly braces) for every single $ variable EXCEPT for these variables: $txt and $helptxt

How can I do this using preg_replace?

EDIT I am reading through a PHP file where array values are defined. I am using $data = get_file_contents(file); than I need a Regex to change all variables that are defined in this file with a $ in front of the word, EXCEPT $txt and $helptxt variables, and I need to have these variables + the '. or ' . that is in front of the variable or at the end. EXAMPLE line in this file could be like so:

$txt['dp_who_forum'] = 'Viewing the forum index of <a href="' . $scripturl . '?action=forum">' .$context['forum_name'].'</a>.';

So I will need it to be replaced to this, instead:

$txt['dp_who_forum'] = 'Viewing the forum index of <a href="{$scripturl}?action=forum">{$context[forum_name]}</a>.';

How can this be done? An开发者_如何转开发d I also need to exclude $helptxt variables from this as well.


Although I'm not 100% sure what you're asking, I think this will do what you want:

preg_replace(
  '/
    \'\h*\.\h*                         # Match a quote and a dot
    (\$(?!(?:help)?txt\b)              # Avoid matching $txt or $helptxt...
       \w+)(?:(\[)([\'"])(\w+)\3(\]))? # ...but do match $var or $arr["idx"]
    \h*\.\h*\'                         # Match a quote and a dot
   /x', 
  '{$1$2$4$5}',
  $string)

The comments help, but the regex still looks like Cthulhu swearing, so let's break it down into pieces. The regex is surrounded by the delimiters /, which are just there because preg_replace requires them. The /x at the end allows us to embed spaces and comments into the regex, which we use to make it more comprehensible. The \'\h*\.\h* incantation, which appears at the beginning and the end, matches ' . and the like. (If you want to match single or double quotes, replace the \' with [\'"].) The ' only needs to be escaped with \ because we're in a single-quoted string. The \h indicates any horizontal whitespace (pretty much a space or a tab), with the * allowing any number. Then the \. is a literal ., and the \h* matches more space.

On the second line, we start to match a variable, which we put in capturing group 1 with parentheses. We first match \$, a literal dollar sign, and then we use (?!(?:help)?txt\b). The interior is simple: (?:help)? optionally matches help (the ?: prevent it from being assigned to a capturing group), and then we match txt, and then there's \b which forces a word break (so that $txta is still matched). The (?!...) is a negative lookahead: it doesn't consume any input, but only matches if its interior doesn't. Thus, we only match here if the variable name isn't txt or helptxt.

On the third line, we finish matching the variable. The \w+ just matches one or more "word characters": alphanumerics and the underscore. After this, we save the variable name into capturing group 1—without the array index, if there is one! We then match something in (?:...)?, which just optionally matches it without saving it to a capturing group. The interior matches the ['array_access'] bit, if it exists. We save lots of capturing groups here so that we can delete the quotes like you want. First, we matches a literal [ with \[, and store this in capturing group 2. Then, we match either a single or a double quote with [\'"], and store this in capturing group 3. We then match another string of word characters, which is the array index, and store it in capturing group 4. We then match whichever quote we started with by matching \3, which is capturing group 3. Finally, we match a closing brace and store it in capturing group five. Finally, we match the dot and quote again. (If you don't want to match $arr["idx"] but just $arr['idx'], then change each of ([\'"]) and \3 to \', and change the replacement string to {$1$2$3$4}.)

We then replace this with '{$1$2$4$5}'. If you recall, $1 is the variable name (and the dollar sign), $2 is the [, $4 is the array index (without quotes), and $5 is the ]. Either all of $2, $4, and $5 are defined or none are, so this only produces square brackets when we want them.

Running this on a string will match and replace every occurrence of the regex, which should, I think, do exactly what you want.


You can do this with two passes, one for the unbracketed style and one for the bracketed style.

For brackets, replace

'\s*\.\s*\$(?!txt|helptxt)(\w+)\['(\w+)'\]\s*\.\s*'  

with

{\$$1[$2]}

Then for the unbracketed variables, replace

'\s*\.\s*\$(?!txt|helptxt)(\w+)\s*\.\s*' 

with

{\$$1}

You'll need to make sure you escape things right in the preg_replace function


Based on what you want, I propose a more simple work-around solution:

  1. Replace $txt & $helptxt by something very strange, such as "_WHAT_IS_THIS_1" and "_WHAT_IS_THIS_2"
  2. Replace all the $variables in the string
  3. Replace "_WHAT_IS_THIS_1" by "$txt" and "_WHAT_IS_THIS_2" by "$helptxt"


preg_replace("!\\'\\s*\\.\\s*\\$((?:([^ht]|t[^x]|tx[^t]|h[^e]|he[^l]|hel[^p]|help[^t]|helpt[^x]|helptx[^t])\\w*|helptxt\\w+|txt\\w+)(?:\\[.+?\\])?)\\s*\\.\\s*\\'!", '{$\\1}', $str)

The regexp is not simple.


It's basically a PHP expression to Smarty conversion. For this simple case and to catch all potential variables use:

$data = preg_replace("/'[\s.]+([$]\w+)[\s.]+'/ims", '{$1}', $data);
$data = preg_replace("/'[\s.]+([$]\w+)\['(\w+)'\][\s.]+'/ims", '{$1[$2]}', $data);

To reverse the process and turn a 'string ... {$var[xyz]} ...' back into a PHP expression 'string ... ' . $var["xyz"] . ' ...' use something like:

$string = var_dump($string, 1);
$string = preg_replace('/\{([$]\w+)\}/', "' . $1 . '", $data);
$string = preg_replace('/\{([$]\w+)\[(\w+)\]\}/', "' . $1['$2'] . '", $data);
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜