PHP:以模式输出字符串



我一直在尝试以下面代码注释部分所示的方式输出输入。不管我怎么努力,我都做不好。你能帮我纠正吗

<?php 
header('Content-type: text/plain');
/*
input: 
1,"3,4",5,6,"7,8,9",10,11
o/p: 
1
3,4
5
6
7,8,9
10
11
*/
$str = '1,"3,4",5,6,"7,8,9",10,11';
//print_r(explode(",", $str));
$arr = explode(",", $str);
$end_qte = false;
$start_qte = false;
foreach($arr as $elm) {
if (stripos($elm,'"') === FALSE && $end_qte) {
echo $elm . "n";
echo "hi";
$end_qte = false;
} else if ($start_qte) {
echo "," . $elm;
} else if (stripos($elm,'"') == 0) {
echo trim($elm,""");
$start_qte = true;
} else if (stripos($elm,'"') == 1) {
echo "," . trim($elm,""") . "n";
$end_qte = true;
$start_qte = false;
}
}
?>

使用我的"状态机";解析文件(基于我最近在javascript中的类似回答(

$str = '1,"3,4",5,6,"7,8,9",10,11';
function tokenize($str)
{
$state = "normal";
$tokens = [];
$current = "";
for ($i = 0; $i < strlen($str); $i++) {
$c = $str[$i];
if ($state == "normal") {
if ($c == ',') {
if ($current) {
$tokens[] = $current;
$current = "";
}
continue;
}
if ($c == '"') {
$state = "quotes";
$current = "";
continue;
}
$current .= $c;
}
if ($state == "quotes") {
if ($c == '"') {
$state = "normal";
$tokens[] = $current;
$current = "";
continue;
}
$current .= $c;
}
}
if ($current) {
$tokens[] = $current;
$current = "";
}
return $tokens;
}
$result = tokenize($str);
/*
Array
(
[0] => 1
[1] => 3,4
[2] => 5
[3] => 6
[4] => 7,8,9
[5] => 10
[6] => 11
)
*/

使用正则表达式很简单:

$str = '1,"3,4",5,6,"7,8,9",10,11';
$matches = [];
preg_match_all('/(".*?")|([^,]+)/', $str, $matches);
$withoutQuotes = array_map(fn($e) => str_replace('"', '', $e), $matches[0]);
echo implode("n", $withoutQuotes);

给出

1
3,4
5
6
7,8,9
10
11

有很多方法可以解析它。

但是,我认为用逗号分隔字符串是错误的,即使它们在一个带引号的字符串中。这样做会使区分分隔符逗号和引号内逗号(只是普通字符(变得困难

我会通过寻找最左边的逗号引号来划分。

我认为最简单的方法是使用正则表达式。


由于您最初使用了许多语言标签,因此这里有一个perl解决方案:

#!/usr/bin/perl
# split -- split up string
master(@ARGV);
exit(0);
# master -- master control
sub master
{
$opt_d = $ENV{"DEBUG"} != 0;
$str = '1,"3,4",5,6,"7,8,9",10,11';
while ($str ne "") {
dbgprt("master: LOOP str='%s'n",$str);
# add ordinary text
if ($str =~ s/^([^,"]+)//) {
$out = $1;
dbgprt("master: NORM out='%s' str='%s'n",$out,$str);
push(@out,$out);
next;
}
# get the delimiter: either comma or quote
$str =~ s/^(.)//;
$out = $1;
dbgprt("master: DLM out='%s' str='%s'n",$out,$str);
# handle a quoted string
if ($out eq '"') {
# get all leading non-quote chars
$str =~ s/([^"]+)//;
$out = $1;
push(@out,$out);
# strip trailing quote
$str =~ s/^"//;
dbgprt("master: QUO out='%s' str='%s'n",$out,$str);
}
}
foreach $out (@out) {
printf("%sn",$out);
}
}
sub dbgprt
{
printf(@_)
if ($opt_d);
}

以下是调试输出:

master: LOOP str='1,"3,4",5,6,"7,8,9",10,11'
master: NORM out='1' str=',"3,4",5,6,"7,8,9",10,11'
master: LOOP str=',"3,4",5,6,"7,8,9",10,11'
master: DLM out=',' str='"3,4",5,6,"7,8,9",10,11'
master: LOOP str='"3,4",5,6,"7,8,9",10,11'
master: DLM out='"' str='3,4",5,6,"7,8,9",10,11'
master: QUO out='3,4' str=',5,6,"7,8,9",10,11'
master: LOOP str=',5,6,"7,8,9",10,11'
master: DLM out=',' str='5,6,"7,8,9",10,11'
master: LOOP str='5,6,"7,8,9",10,11'
master: NORM out='5' str=',6,"7,8,9",10,11'
master: LOOP str=',6,"7,8,9",10,11'
master: DLM out=',' str='6,"7,8,9",10,11'
master: LOOP str='6,"7,8,9",10,11'
master: NORM out='6' str=',"7,8,9",10,11'
master: LOOP str=',"7,8,9",10,11'
master: DLM out=',' str='"7,8,9",10,11'
master: LOOP str='"7,8,9",10,11'
master: DLM out='"' str='7,8,9",10,11'
master: QUO out='7,8,9' str=',10,11'
master: LOOP str=',10,11'
master: DLM out=',' str='10,11'
master: LOOP str='10,11'
master: NORM out='10' str=',11'
master: LOOP str=',11'
master: DLM out=',' str='11'
master: LOOP str='11'
master: NORM out='11' str=''
1
3,4
5
6
7,8,9
10
11

最新更新