logi sisse meist KKK

Probleem järgmine. Kasutusel on vorming, mis sisaldab tabeli kujul teatud numbrilist vastavust:

[ajatempel;]väärtus1=vaste1;väärtus2=vaste2;...;väärtus(n)=vaste(n);

Näiteks:

1=2;3=4;5=6;
1234;5=6;7=8;

Kuidas oleks kõige lihtsam kontrollida, kas sisendstring vastab sellele reeglile, kontrolliks seda, et vorming hõivaks terve stringi, annaks välja kõik numbrid ja kontrolliks ka ajatempli olemasolu? Proovisin seda teha regulaaravaldisega, kuid rühmitatud kontroll ei töötanud kuigi hästi:

<?php
if(preg_match('/^(|\d+;)((\d+)=(\d+);)+$/','123;4=5;6=7;8=9;',$reg))
   print_r($reg);
?>

vastus:

Array
(
[0] => 123;4=5;6=7;8=9;
[1] => 123;
[2] => 8=9;
[3] => 8
[4] => 9
)

Vastus jätab vahele paarid (4=5) ja (6=7) ning paneb sekka juppe, mida ei ole vaja.

Muidugi võiksin süntaksikontrolli käsitsi teha, aga juurdlen, kas seda ei saaks teha lihtsamini.

küsitud Mar 13 '12 at 13:06

Teet65's gravatar image

Teet65
175911

edited Mar 28 '12 at 16:02


Hetkel oleks lihtsam kontrollida süntaksi regex-ga aga lahti lõhkuda teise käsuga.

$data = '123;4=5;6=7;8=9;';
$regex = '/^(\d+;)(\d+=\d+;)+$/';
if (preg_match($regex,$data)){
    $arr = split(";", $data)
}

Loomulikult, siis olenevalt vajadusest iga element veel eraldi lõhkuda.

link

vastatud Mar 13 '12 at 18:36

egon's gravatar image

egon ♦♦
771239

edited Mar 13 '12 at 18:40

Nii vist tulekski teha, ainult muudaksin regulaaravaldise järgmiseks: $regex = '/^(|d+;)(d+=d+;)+$/'; see püüab kinni ka puuduva ajatempliga rea.

(Mar 13 '12 at 20:34) Teet65

Juppide vahelejätmise kohta: PHP manuaalis see dokumenteeritud ei ole, aga alloleva PCRE teegi juures on kirjas, et korduvate rühmade sobitamisel antakse iga rühma kohta tagasi ainult viimane vaste. Kui on ette teada mingi paaride arvu ülempiir, siis saab konstrueerida piisava pikkusega kordusteta regulaaravaldise.

Näiteks

$max_paare = 5;
$regex = '/^(\d+;)?';
for ($i = 0; $i < $max_paare; ++$i)
    $regex .= '((\d+)=(\d+);)?';
$regex .= '$/';

järel on

if (preg_match($regex,'123;4=5;6=7;8=9;',$res))
    print_r($res);

väljund

Array
(
    [0] => 123;4=5;6=7;8=9;
    [1] => 123;
    [2] => 4=5;
    [3] => 4
    [4] => 5
    [5] => 6=7;
    [6] => 6
    [7] => 7
    [8] => 8=9;
    [9] => 8
    [10] => 9
)

Liigsete juppide saamise kohta: selleks, et näidata, et mingid sulud on grupeerimiseks, aga neile vastavat teksti ei ole vaja tagastada, tuleks grupi alguses ( asemel kasutada (?:.

Näiteks

$max_paare = 5;
$regex = '/^(?:(\d+);)?';
for ($i = 0; $i < $max_paare; ++$i)
    $regex .= '(?:(\d+)=(\d+);)?';
$regex .= '$/';

järel on

if (preg_match($regex,'123;4=5;6=7;8=9;',$res))
    print_r($res);

väljund

Array
(
    [0] => 123;4=5;6=7;8=9;
    [1] => 123
    [2] => 4
    [3] => 5
    [4] => 6
    [5] => 7
    [6] => 8
    [7] => 9
)

Tervele avaldisele vastanud teksti tagastamist minu teada keelata ei saa, seega ainus võimalus on $reg[0] olemasolu ignoreerida (või kui on suur soov kasutada foreach ($reg as $val), siis see lihtsalt ära kustutada).

Seda, kas rea alguses mittekohustuslik ajatempel esines või mitte, saab vaadata $reg pikkuse paarsuse järgi.

link

vastatud Mar 13 '12 at 17:18

Ahto%20Truu's gravatar image

Ahto Truu ♦♦
6596711

Ideel oleks jumet, kuid kahjuks ei ole vormingule määratud tabeli pikkust, see võib olla teoreetiliselt lõputu. Samuti kasutan PHP asemel hoopis üht regulaaravaldise teeki Delphi jaoks ja see on väga pikkade sulge sisaldavate avaldiste suhtes tõrges, samuti ei toeta see "(?:"-regulaaravaldise laiendust.

(Mar 13 '12 at 20:34) Teet65

Tere, kui Delphiga tegemist, miks mitte selline kood...

var p : TStringlist; i : integer; begin try p:=TStringlist.Create; p.Delimiter:=';'; p.DelimitedText:='123;4=5;6=7;8=9'; if (p.count>0) and (strtointdef(p.Strings[0],-1)<>-1) then for i:=1 to p.Count-1 do writeln(strtointdef(p.Names[i],-1),' : ',strtointdef(p.ValueFromIndex[i],-1)); finally p.Free; end;

(Mar 13 '12 at 21:21) Ingmar Tammeväli

Ikka postitage Delphi küsimuste juurde PHP koodinäide ilma mingit lisavihjet andmata ;)

(Mar 13 '12 at 21:34) Ahto Truu ♦♦

Njah, alahindasin siinse rahva leidlikkust, ehkki regulaaravaldise parsimise kood oleks selle Delphi komponendiga märksa kohmakam olnud. Arvestan Ahto mõttega edaspidi ja kaalun nüüd ka TstringList kasutamist.

(Mar 13 '12 at 23:00) Teet65
function parse_line($line) {
  preg_match_all('/(^\d+);|(\d+)=(\d+);|(.+)/',$line,$reg);

  // kõik, mis EI TOHI real olla läks osasse (.+)
  // see peab tühi olema, kontrollime
  $oktest = array_unique($reg[4]);
  if (count($oktest) != 1 || !empty($oktest[0]))
    return false;
  else {
      if ($reg[1][0]) { // kui timestamp oli olemas
        array_shift($reg[2]);
        array_shift($reg[3]);
      }
    return array('tstamp' => $reg[1][0], 'keys' => $reg[2], 'vals' => $reg[3]);
  }
}

Testimiseks:

$tests = array(
 '123;4=5;6=7;8=9;a'    // false
,'123;viga4=5;6=7;8=9;' // false
,'123;4=5;6=7;8=9;' // {"tstamp":"123","keys":["4","6","8"],"vals":["5","7","9"]}
,'4=5;6=7;8=9;'     // {"tstamp":"","keys":["4","6","8"],"vals":["5","7","9"]}
);

foreach($tests as $t) print $t . "\n" . json_encode(parse_line($t)) . "\n\n";
link

vastatud Mar 23 '12 at 02:27

Kaiko%20Kaur's gravatar image

Kaiko Kaur
2306711

edited Mar 26 '12 at 22:44

Mulle tundub, et see lahendus ei kontrolli, kas rida on nõutud kujul.

(Mar 23 '12 at 09:59) Ahto Truu ♦♦

Näites on 2 esimest rida vigased ja neile tuleb vastuseks false.

(Mar 23 '12 at 10:01) Kaiko Kaur

Ma ei tea kui eetiline on tagantjärgi algset postitust veel muuta, aga lisasin kommentaarid.

(Mar 26 '12 at 22:43) Kaiko Kaur
Sinu vastus
lülita eelvaade

Jälgi seda küsimust

By Email:

Pärast sisselogimist saad tellida muudatuse teavitusi siit

By RSS:

Answers

Answers and Comments

Markdown Basics

  • *kaldkiri* või __kaldkiri__
  • **paks kiri** või __paks kiri__
  • link:[tekst](http://url.com/ "pealkiri")
  • pilt?![alt tekst](/path/img.jpg "pealkiri")
  • nummerdatud nimekiri: 1. Foo 2. Bar
  • to add a line break simply add two spaces to where you would like the new line to be.
  • põhilised HTML märgendid on samuti toetatud

Pinu tööpakkumised

kõik pakkumised »

Küsimuse sildid:

×6

küsitud: Mar 13 '12 at 13:06

nähtud: 2,504 korda

viimati uuendatud: Mar 28 '12 at 16:02

Litsents: Creative Commons Attribution License | Kontakt: info@pinu.ee