PCRE незахватывающий поиск

berkut

Новичок
PCRE незахватывающий поиск

Есть строки:
Satellite M35x-S149 (PSA72U-00T00U) Celeron M 340 1.5Ghz..........
VGN-A170-1756DW Pentium M 735 1.7A Ghz.........
Нужно выдернуть из 1-ой строки
Satellite M35x-S149
из 2-ой:
VGN-A170-1756DW
PHP:
$pattern = '#.+?(?=(\(.+?\) )?celeron|pentium|new|centrino)#i'
По идее, всё, что находится в (?=....) не должно заватываться и в этой конструкции допустимы любые выражения.
У меня-же получается:
Satellite M35x-S149 (PSA72U-00T00U)
и
VGN-A170-1756DW
+ к этому, не понятно по какому принципу, иногда формируется втиорой карман с (PSA72U-00T00U)

-~{}~ 11.09.05 04:08:

почитал, наверно всё-таки нормальное поведение - это захват во 2-ой карман (PSA72U-00T00U)
Но почему многие строки получаются Satellite M35x-S149 (PSA72U-00T00U) и при этом второго кармана нет. Т.е. получается, скобки съедает первая часть: '#.+?
 

Profic

just Profic (PHP5 BetaTeam)
Неверная расстановка скобок.
То что в скобочках будет захватываться в первый "карман" только если после них будет написано celeron

PHP:
<?php
$a = 'Satellite M35x-S149 (PSA72U-00T00U) Pentium M 340 1.5Ghz..........
VGN-A170-1756DW Pentium M 735 1.7A Ghz';
$pattern = '#^.+?(?=(\(.+?\) )?celeron|pentium|new|centrino)#mi';
preg_match_all($pattern, $a, $matches);
var_dump($matches);
?>
^Z
Код:
array(2) {
  [0]=>
  array(2) {
    [0]=>
    string(36) "Satellite M35x-S149 (PSA72U-00T00U) "
    [1]=>
    string(16) "VGN-A170-1756DW "
  }
  [1]=>
  array(2) {
    [0]=>
    string(0) ""
    [1]=>
    string(0) ""
  }
}
E:\work\web\SDN\recipe-nddocs\php>php
PHP:
<?php
$a = 'Satellite M35x-S149 (PSA72U-00T00U) Pentium M 340 1.5Ghz..........
VGN-A170-1756DW Pentium M 735 1.7A Ghz';
$pattern = '#^.+?(?=(\(.+?\) )?(?:celeron|pentium|new|centrino))#mi';
preg_match_all($pattern, $a, $matches);
var_dump($matches);
?>
^Z
Код:
array(2) {
  [0]=>
  array(2) {
    [0]=>
    string(20) "Satellite M35x-S149 "
    [1]=>
    string(16) "VGN-A170-1756DW "
  }
  [1]=>
  array(2) {
    [0]=>
    string(16) "(PSA72U-00T00U) "
    [1]=>
    string(0) ""
  }
}
E:\work\web\SDN\recipe-nddocs\php>
 

berkut

Новичок
я тоже уже разобрался. допёрло, что "список или" нужно в скобки групировать. То, что иногда образовывался 2-ой карман, а иногда нет, происходило из-за того, что после скобок могло быть несколько пробелов. что у меня получилось
PHP:
$pattern = '#[^(]+?(?=(\([^)]+\) +)?(celeron|pentium|new|centrino))#i';
А что означает (?: - искал, но ничего не нашёл. По работе, похоже на (?=
 

berkut

Новичок
Э-э, а что такое позиционная проверка?

-~{}~ 11.09.05 06:04:

кое-что всё таки нашёл, насчёт (?: и (?=
по идее, должно быть:
PHP:
$str = 'zx/jk/iop';
$pattern = '#^[a-z]+(?:.).+$#';
$pattern2 = '#^[a-z]+(?=.).+$#';
preg_match($pattern, $str, $m);
var_dump($m); // zxjk/iop
preg_match($pattern2, $str, $m);
var_dump($m); // 'zx/jk/iop'
но оба прега выводят zx/jk/iop
 

Profic

just Profic (PHP5 BetaTeam)
[m]reference.pcre.pattern.syntax#regexp.reference.assertions[/m]

PHP:
$str = 'zx/jk/iop'; 
$pattern = '#^([a-z]+)(?:.)(.+)$#'; 
$pattern2 = '#^([a-z]+)(?=.)(.+)$#'; 
preg_match($pattern, $str, $m); 
var_dump($m); // 1:zx 2:jk/iop 
preg_match($pattern2, $str, $m); 
var_dump($m); // 1:zx 2:/jk/iop
 

berkut

Новичок
божественно и бесподобно! псре на русском языке! буду курить заного
 

uchenik

Новичок
Интересно почему ты применяешь позиционные проверки если не знаешь что это такое?
 

berkut

Новичок
Почему не знаю? Я же описал их суть 2 постами выше, только небольшая ошибочка со скобками вышла. А вообще, я был уверен, что (?= - это незахватывающий карман, а про (?: я вообще не слшал(читал книжку по псре с примерами на перле)
В моём случае, можно использовать как (?: так и (?=
Код Profic можно периписать используя и то и другое
 
Сверху