解析字符串中的字符串?

时间:2009-07-01 18:39:55

标签: php parsing variables string

我有一个接受字符串参数的函数,例如:“var1 = val1 var2 = val2 var3 ='vals列表'”;

我需要解析这个字符串并选出var / val组合。这很容易,直到引入类似var3 ='vals列表'的东西。显然我不能使用白色空格分隔符将字符串分解为数组,这会使我陷入困境。我想从这个字符串创建一个数组,并且正确分配了var / val对,如果我有类似var3的话,我怎么能这样做呢?

8 个答案:

答案 0 :(得分:1)

如果字符串的格式是,那么您可以执行以下操作:

$string = "var1=val1 var2=val2 var3='this is a test'";

$vars = array();
$i = 0;
while ($i < strlen($string)) {

    $eqIndex = strpos($string, "=", $i);
    $varName = substr($string, $i, $eqIndex - $i);

    $i = $eqIndex + 1;

    if ($string[$i] == "'") 
    {
        $varEndIndex = strpos($string, "'", ++$i);
    }
    else
    {
        $varEndIndex = strpos($string, " ", $i);
        if ($varEndIndex === FALSE) $varEndIndex = strlen($string);
    }

    $varValue = substr($string, $i, $varEndIndex - $i);

    $vars[$varName] = $varValue;

    $i = $varEndIndex + 1;
}

print_r($vars);

编辑:

更强大的函数,用于处理引用值中的转义字符:

function getVarNameEnd($string, $offset) {

    $len = strlen($string);
    $i = $offset;
    while ($i < $len) {

        if ($string[$i] == "=")
            return $i;
        $i++;
    }

    return $len;
}

function getValueEnd($string, $offset) {

    $len = strlen($string);
    $i = $offset;
    if ($string[$i] == "'") {
        $quotedValue = true;
        $i++;
    }
    while ($i < $len) {

        if ($string[$i] == "\\" && $quotedValue)
            $i++;
        else if ($string[$i] == "'" && $quotedValue)
            return $i + 1;
        else if ($string[$i] == " " && !$quotedValue)
            return $i;
        $i++;
    }

    return $len;
}

function getVars($string) {

    $i = 0;
    $len = strlen($string);
    $vars = array();
    while ($i < $len) {

        $varEndIndex = getVarNameEnd($string, $i);
        $name = substr($string, $i, $varEndIndex - $i);
        $i = $varEndIndex + 1;

        $valEndIndex = getValueEnd($string, $i);
        $value = substr($string, $i, $valEndIndex - $i);
        $i = $valEndIndex + 1;

        $vars[$name] = $value;
    }

    return $vars;
}

$v = getVars("var1=var1 var2='this is a test' var3='this has an escaped \' in it' var4=lastval");
print_r($v);

答案 1 :(得分:1)

传统上,查询字符串使用&amp;作为分隔符而不是空格。

如果您可以这样做,那么只需使用parse_str即可获取数据。

如果没有,你需要做正则表达式:

preg_match_all('/(\S*)=('.*?'|\S*)/g', $your_string, $matches);
print_r($matches);

答案 2 :(得分:0)

您可以使用正则表达式查找所有匹配的var = val对,例如

(\w[0-9A-Za-z]+)=(\'?\w([0-9A-Za-z ]|\\\'|\\=)+\'?)

然后你可以使用preg_match_all从那里解析它们,如果第二组的字符串以'你可以解析列表的字符开头。

答案 3 :(得分:0)

我担心这个问题无法通过简单的正则表达式或简单的拆分来解决。看看PHP 5.3中的str_getcsv()函数。我认为你可以做到你想要的。

array str_getcsv  ( string $input  [, string $delimiter  [, string $enclosure  [, string $escape  ]]] )

您可以将分隔符指定为空格而不是逗号和机箱作为单引号而不是双引号。如果可以的话,挖掘这个功能的实现,理解它,并从中学习。否则,请使用PHP 5.3来使用它。

编辑:如果您没有PHP 5.3:

if(!function_exists('str_getcsv')) {
    function str_getcsv($input, $delimiter = ",", $enclosure = '"', $escape = "\\") {
        $fp = fopen("php://memory", 'r+');
        fputs($fp, $input);
        rewind($fp);
        $data = fgetcsv($fp, null, $delimiter, $enclosure); // $escape only got added in 5.3.0
        fclose($fp);
        return $data;
    }
}

信用:http://www.electrictoolbox.com/php-str-getcsv-function/

编辑:以下是Perl中的实现:Text::CSV。您可以下载源代码并查看算法。如果你愿意的话:):

答案 4 :(得分:0)

没有考虑过整个事情,但是这个怎么样?对于这么小的任务来说,可能是一个太少的代码:)

<?php
  function parse_vars($string)
  {
    $exploded = explode(" ", $string);
    $return = array();
    foreach($exploded AS $entry){
      if(strpos($entry, "=") === false){      
        $return[$current] .= " ".$entry;
      }else{
        list($key, $value) = explode("=", $entry);
        $return[$key] = $value;
        $current = $key;
      }
    }   
    return $return;
  }

  $string = "var1=val1 var2=val2 var3='a list of vals'";
  print_r(parse_vars($string));
  die();
?>

顺便说一句,我仍然更喜欢使用"(\S*)=('.*?'|\S*)" ...

的正则表达式解决方案

答案 5 :(得分:0)

也许你想要parse_str()函数?

以下是来自PHP.net的示例:

<?php
$str = "first=value&arr[]=foo+bar&arr[]=baz";
parse_str($str);
echo $first;  // value
echo $arr[0]; // foo bar
echo $arr[1]; // baz

parse_str($str, $output);
echo $output['first'];  // value
echo $output['arr'][0]; // foo bar
echo $output['arr'][1]; // baz

?>

它似乎完全符合您的要求。

答案 6 :(得分:-1)

好的,你无法改变它。我会使用这样的算法:

1)用唯一的ID替换引号中包含的所有字符串,并将ID存储在数组中。

所以

  

var1 = val1 var2 = val2 var3 ='vals列表'

变为

  

var1 = val1 var2 = val2 var3 = asifab

     

array(“asifab”=&gt;'一系列val')

2)按空格分割

  

数组(“var1 = val1”,“var2 = val2”,“var3 = asifab”)

     

array(“asifab”=&gt;'一系列val')

3)按等号划分

  

array(“var1”=&gt;“val1”,“var2”=&gt;“val2”,“var3”=&gt;“asifab”)

     

array(“asifab”=&gt;'一系列val')

4)对于每个值,查看它是否在您的数组中,如果是,则将数组值除以空格并将其用作值

  

array(“var1”=&gt;“val1”,“var2”=&gt;“val2”,“var3”=&gt;数组(“a”,“list”,“of”,“values”))

答案 7 :(得分:-1)

将RegEx与preg_split()一起使用?

我对RE不太满意,但我确信你可以使用它来防止在单引号内拆分字符串。