我有一个flatfile数据库,它是由分隔符分隔的数据。
我允许人们在他们的输入中使用分隔符,但我确保事先用\
转义它。
问题是我的explode()
函数仍然试图拆分转义的分隔符,所以如何告诉它忽略它们?
答案 0 :(得分:8)
请改用preg_split。通过使用正则表达式,只有在前缀为反斜杠的情况下才能匹配分隔符。
编辑:
preg_split('~(?<!\\\)' . preg_quote($delimeter, '~') . '~', $text);
答案 1 :(得分:2)
这里的解决方案都没有正确处理任意数量的转义字符,或者它们将它们留在输出中。这是另一种选择:
function separate($string, $separator = '|', $escape = '\\') {
if (strlen($separator) != 1 || strlen($escape) != 1) {
trigger_error(__FUNCTION__ . ' requires delimiters to be single characters.', E_USER_WARNING);
return;
}
$segments = [];
$string = (string) $string;
do {
$segment = '';
do {
$segment_length = strcspn($string, "$separator$escape");
if ($segment_length) {
$segment .= substr($string, 0, $segment_length);
}
if (strlen($string) <= $segment_length) {
$string = null;
break;
}
if ($escaped = $string[$segment_length] == $escape) {
$segment .= (string) substr($string, ++$segment_length, 1);
}
$string = (string) substr($string, ++$segment_length);
} while ($escaped);
$segments[] = $segment;
} while ($string !== null);
return $segments;
}
这会将foo\|ba\r\\|baz|
之类的原始字符串处理为foo|bar\
,baz
和一个空字符串。
如果要在输出中保留转义字符,则必须修改该函数。
注意:如果您使用mb function overloading,则会出现不可预测的行为。
答案 2 :(得分:0)
key1=val1;key2=val2start\;val2end;key3=val3\\;key4=val4\\\;key5=val5\\\\;key6=val6
/(.*?[^\\](\\\\)*?);/
<?php
$data="key1=val1;key2=val2start\\;val2end;key3=val3\\\\;key4=val4\\\\\\;key5=val5\\\\\\\\;key6=val6";
$regex='/(.*?[^\\\\](\\\\\\\\)*?);/';
preg_match_all($regex, $data.';', $matches);
print_r($matches[1]);
Array
(
[0] => key1=val1
[1] => key2=val2start\;val2end
[2] => key3=val3\\
[3] => key4=val4\\\;key5=val5\\\\
[4] => key6=val6
)
答案 3 :(得分:0)
您将发现此解决方案比对大字符串使用正则表达式更有用。我使用一个流来允许使用fgetcsv
,该流已针对此类情况进行了优化。
<?php
function escaped_explode($string,$delimit,$escape=NULL,$enclosure=NULL,$max_line_length=0){
$r=[];
$stream = fopen('php://memory','r+');
fwrite($stream, $string);
rewind($stream);
while (($data = fgetcsv($stream,$max_line_length,$delimit,$enclosure,$escape)) !== FALSE)
$r=array_merge($r,$data);
fclose($stream);
return $r;
}
?>
用法:
$pipelined_values = escaped_explode($source,'|','\\');
这也很方便,因为您可以选择使用诸如引号之类的附件,而不是仅使用转义字符。如果您遇到解析某人的JSON值或其他语法的斑点的感觉,那么这很好,因为您可以同时封装和转义。
$source= <<<JSON
'{ "key":"val", "n":0}',
'{ "key":"val", "n":1, "name": "French du\'Name" }',
'{ "key":"val", "n":2}'
JSON;
可以解释
<?php
$objects=[];
$raw= escaped_explode($source, ',', '\\', "'");
foreach($raw as $r)
$objects[] = json_decode($r);
?>
答案 4 :(得分:-1)
preg_split
肯定会给你你想要的东西。但是,我写了这个小片段,它似乎运作良好。如果你不想使用preg_split,请点击:
$delim = ',';
$string = "Hello,World,This\\,is escaped,This is not";
$array = explode($delim, $string);
$finalArray = array();
var_dump($array);
for($i = 0; $i < count($array); $i++) {
$strToPush = $array[$i];
while("\\" == substr($array[$i], -1)) {
$i++;
$strToPush .= $delim . $array[$i];
}
array_push($finalArray, $strToPush);
}
var_dump($finalArray);
给出了输出:
阵列
0 =&gt;字符串&#39;您好&#39; (长度= 5)
1 =&gt; string&#39; World&#39; (长度= 5)
2 =&gt;字符串&#39;这个&#39; (长度= 5)
3 =&gt;字符串&#39;被转义&#39; (长度= 10)
4 =&gt;字符串&#39;这不是&#39; (长度= 11)阵列
0 =&gt;字符串&#39;您好&#39; (长度= 5)
1 =&gt; string&#39; World&#39; (长度= 5)
2 =&gt;字符串&#39;这个\,被转义&#39; (长度= 16)
3 =&gt;字符串&#39;这不是&#39; (长度= 11)