Hmm, once I sat down to tackle this problem, it didn't get nearly as hairy as I expected it to be. After some muddling through the online docs, and many, many obscenities, I produced this, which seems quite workable, and doesn't present any security risks that I can see:
<?php
// where we do all our magic
function expand_escape($string) {
return preg_replace_callback(
'/\\\([nrtvf]|[0-7]{1,3}|x[0-9A-Fa-f]{1,2})?/',
create_function(
'$matches',
'return ($matches[0] == "\\\\") ? "" : eval( sprintf(\'return "%s";\', $matches[0]) );'
),
$string
);
}
// a string to test, and show the before and after
$before = 'Quantity:\t500\nPrice:\t$5.25 each';
$after = expand_escape($before);
var_dump($before, $after);
/* Outputs:
string(34) "Quantity:\t500\nPrice:\t$5.25 each"
string(31) "Quantity: 500
Price: $5.25 each"
*/
?>
edit: heh, I just noticed Brad's solution after I posted my own. I need to remember to refresh the page before I follow up, I guess. At any rate, his seems to be a little cleaner, as it doesnt require the lambda function. i also forgot the 'x' for hex values, though I removed the 'i' flag and added 'A-F' to the range, since \N, \R, \T, etc aren't valid escape sequences. this is the final function I ended up with (thanks brad):
<?php
function expand_escape($string) {
return preg_replace(
'/(?<!\\\)(\\\(?:[nrtvf]|[0-7]{1,3}|x[0-9A-Fa-f]{1,2}))/e',
'eval(\'return "$1";\')',
$string
);
}