Bir dize içinde bir dize ayrıştırma?

8 Cevap php

Ben gibi bir dize parametresi kabul eden bir işlevi vardır: "var1 = val1 var2 = val2 değ3 = 'vals listesi'";

Ben bu dizeyi ayrıştırmak ve var / val kombinasyonun ortaya çıkarmak gerekir. Bu 'vals listesi' değ3 = gibi bir şey tanıtan kadar yeterince kolaydır. Açıkçası bana tür sıkışmış olan beyaz boşluk sınırlayıcı kullanarak bir diziye dize patlayabilir olamaz. Ben düzgün atanan var / val çiftleri ile bu dizeden bir dizi oluşturmak istiyorsanız, bir durumda ben değişk3 gibi bir şey var burada ben bunu nasıl yapabilirim?

8 Cevap

dizenin biçim is taş ayarlarsanız, gibi bir şey yapabilirsiniz:

$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);

EDIT:

Kote değerleri kaçtı karakter kolları daha sağlam fonksiyonu:

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);

Sorgu dizeleri kullanmak ve bu yüzden geleneksel olarak sınırlayıcı değil, boşluk gibi.

Bunu yapabilirsek, o zaman sadece parse_str dışarı veri almak için kullanabilirsiniz.

Değilse, regex yapmak gerekir:

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

Gibi tüm eşleşen var = val çiftleri bulmak için normal bir ifade kullanabilirsiniz

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

ikinci grubun dize listesini ayrıştırmak bir 'karakteri ile başlıyorsa, o zaman, preg_match_all oradan onları ayrıştırmak için kullanabilirsiniz.

Her şey çok düşündün, ama ne bu konuda değil mi? Belki böyle küçük bir görev için biraz fazla kod :)

<?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();
?>

Bu arada ben hala ile regex çözümü tercih "(\S*)=('.*?'|\S*)" ...

Belki parse_str () fonksiyonu istiyorsun?

İşte PHP.net gelen örnek:

<?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

?>

Bu sizin için tam olarak ne aradığınızı yapmak gibi görünüyor.

Ben bu sorun basit regex veya basit bölme ile çözülemez korkuyorum. PHP 5.3 'te str_getcsv() fonksiyonuna bir göz var. Ben bunu size tam olarak ne istiyorsun yapabilirsiniz düşünüyorum.

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

Sen tek tırnak yerine çift tırnak olarak boşluk yerine virgül ve muhafaza gibi sınırlayıcı belirtebilirsiniz. Eğer yapabiliyorsanız, bu işlevin uygulanması kazıp, onu anlamak ve öğrenmek. Aksi takdirde PHP 5.3 kullanmak için olsun.

Edit: Orada, PHP 5.3 yoksa:

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;
    }
}

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

Edit: İşte Perl uygulama bulunuyor: Text::CSV. Sen kaynak indirebilir ve algoritmaları görebilirsiniz. Eğer bunun için ise :)

Ile RegEx kullanın preg_split()?

Ben RE ile büyük değilim, ama tek tırnak içinde dize bölme önlemek için kullanabilirsiniz eminim.

Tamam, bunu değiştiremezsiniz. Böyle bir algoritma kullanır:

1) benzersiz bir kimliği ile tırnak içinde bulunan bütün dizeleri değiştirin ve bir dizi Kimliğini saklamak.

Bu yüzden

var1 = val1 var2 = val2 değ3 = 'vals listesi'

olur

var1 = val1 var2 = val2 değ3 = asifab

array ("asifab" => 'vals listesi')

2) boşluklarla Böl

array ("var1 = val1", "var2'ye = val2", "değ3 = asifab")

array ("asifab" => 'vals listesi')

3) eşit işaretleri ile bölünmüş

array ("var1" => "val1", "var2'ye" => "val2", "değ3" => "asifab")

array ("asifab" => 'vals listesi')

4), her değer için bu dizide eğer, görmek, ve eğer, boşluklarla dizi değeri bölmek ve değer olarak kullanmayın

array ("var1" => "val1", "var2'ye" => "val2", "değ3" => array, "değerler", "yorum" ("a", "listesi",))