2011-10-19 33 views
5

Tôi vẫn đang học rất nhiều về PHP và thay đổi chuỗi là điều mà tôi quan tâm. Tôi đã sử dụng preg_match trước đây cho những thứ như xác nhận địa chỉ email hoặc chỉ tìm kiếm các yêu cầu.Cách preg_match_all() xử lý các chuỗi?

Tôi vừa xuất phát từ bài đăng này What's wrong in my regular expression? và tò mò là tại sao hàm preg_match_all tạo 2 chuỗi, 1 w/một số ký tự bị tước và sau đó là w/đầu ra mong muốn.

Từ những gì tôi hiểu về hàm là nó đi qua ký tự chuỗi ký tự bằng cách sử dụng RegEx để đánh giá việc cần làm với nó. RegEx này có thể được cấu trúc theo cách như vậy để bỏ qua mục nhập mảng đầu tiên và chỉ tạo ra kết quả mong muốn không?

và do đó bạn không cần phải đi đến các chủ đề khác

$str = 'text^name1^Jony~text^secondname1^Smith~text^email1^example- 
     [email protected]~'; 

preg_match_all('/\^([^^]*?)\~/', $str, $newStr); 

for($i=0;$i<count($newStr[0]);$i++) 
{ 
    echo $newStr[0][$i].'<br>'; 
} 

echo '<br><br><br>'; 

for($i=0;$i<count($newStr[1]);$i++) 
{ 
    echo $newStr[1][$i].'<br>'; 
} 

chí này ra

^Jony ~
^Smith ~
^[email protected]~


Jony
Smith
[email protected]

Tôi tò mò nếu lý do cho 2 mục nhập mảng là do sytax gốc của chuỗi hoặc nếu đó là phản hồi xử lý bình thường của hàm. Xin lỗi nếu điều này không nên ở đây, nhưng tôi thực sự tò mò về cách thức hoạt động của nó.

cảm ơn, Brodie

+0

Đầu ra sẽ luôn chứa toàn bộ kết quả phù hợp và mục nhập cho từng nhóm chụp trong biểu thức của bạn. –

+0

Không phải là câu trả lời, nhưng thú vị cần lưu ý ở đây là cờ 'PREG_SET_ORDER', sẽ trả về một danh sách kết quả đơn giản hơn. Và trong khi bạn không thể xóa mục nhập mảng '[0]' cho đối sánh hoàn chỉnh, bạn có thể tách nội dung của nó bằng cách sử dụng '\ K' trong regex. – mario

Trả lời

2

Đó là hành vi tiêu chuẩn cho preg_match và preg_match_all - chuỗi đầu tiên trong "giá trị phù hợp" mảng là chuỗi FULL đã bị bắt bởi mẫu regex. Các giá trị mảng tiếp theo là 'nhóm nắm bắt', sự tồn tại của chúng phụ thuộc vào vị trí/vị trí của các cặp () trong mẫu regex.

Trong trường hợp của regex của bạn, /\^([^^]*?)\~/, chuỗi hợp đầy đủ sẽ

^ Jony ~ 
|  |  | 
^ ([^^]*?) ~ -> $newstr[0] = ^Jony~ 
       -> $newstr[1] = Jony (due to the `()` capture group). 
+0

Ah tôi hiểu, do đó, điều đầu tiên nó làm là tìm văn bản bắt đầu w/^ và kết thúc bằng ~ và sau đó biểu thức thứ hai trong() lấy mọi thứ sau^trừ ~. Tôi đoán tò mò là tốt nhất của tôi, nếu [^^] *? nói với nó để lấy các văn bản sau khi '^' tại sao sau đó hiện nó không lấy '~'? – Brodie

+0

Nó có, nhưng '~' không nằm trong nhóm chụp của bạn, vì vậy nó sẽ chỉ hiển thị trong phần '[0]'. Bạn có thể xem xét toàn bộ mẫu regex là một nhóm chụp chính vì vậy mà capture ảo được lưu trữ trong '[0]', và sau đó bất kỳ capture nào bạn tạo một cách rõ ràng với '()' đi vào [1], [2], vv ... –

+0

'[^^] *?' dịch thành 'nhiều ký tự (*, '0 hoặc hơn') KHÔNG phải là^([^^]), theo kiểu không tham lam (?). –

0

[0] chứa toàn bộ trận đấu, trong khi [1] chỉ một phần (phần bạn muốn trích xuất) ... Bạn có thể làm var_dump($newStr) để xem cấu trúc mảng, bạn sẽ hình dung nó ra .

$str = 'text^name1^Jony~text^secondname1^Smith~text^email1^example- 
     [email protected]~'; 

preg_match_all('/\^([^^]*?)\~/', $str, $newStr); 

$newStr = $newStr[1]; 
foreach($newStr as $key => $value) 
{ 
    echo $value."\n"; 
} 

này sẽ cho kết quả (biểu hiện kết quả kỳ lạ, chưa sửa đổi) trong ...

Jony 
Smith 
example- 
     [email protected] 
1

Khi manual tiểu bang, đây là kết quả dự kiến ​​(đối với lá cờ mặc định PREG_PATTERN_ORDER). Mục nhập đầu tiên của $newStr chứa tất cả các đối sánh mẫu đầy đủ, kết quả tiếp theo tất cả các kết quả phù hợp cho mẫu con đầu tiên (trong dấu ngoặc đơn), v.v.

+0

ah nó có ý nghĩa bây giờ ... cảm ơn bạn đã trả lời – Brodie

1

Mảng đầu tiên trong kết quả của preg_match_all trả về các chuỗi khớp với toàn bộ mẫu bạn đã chuyển đến hàm preg_match_all(), trong trường hợp của bạn/\^([^^] *?) \ ~ /. Các mảng tiếp theo trong kết quả chứa các kết quả phù hợp cho các dấu ngoặc đơn trong mẫu của bạn.Có lẽ nó là dễ hiểu với một ví dụ:

$string = 'abcdefg'; 
preg_match_all('/ab(cd)e(fg)/', $string, $matches); 

Các $ phù hợp với mảng sẽ

array(3) { 
    [0]=> 
    array(1) { 
    [0]=> 
    string(7) "abcdefg" 
    } 
    [1]=> 
    array(1) { 
    [0]=> 
    string(2) "cd" 
    } 
    [2]=> 
    array(1) { 
    [0]=> 
    string(2) "fg" 
    } 
} 

Mảng đầu tiên sẽ chứa các trận đấu của toàn bộ mô hình, trong trường hợp này 'abcdefg'. Mảng thứ hai sẽ chứa kết quả phù hợp cho bộ ngoặc đơn đầu tiên, trong trường hợp này là 'cd'. Mảng thứ ba sẽ chứa kết quả phù hợp cho bộ ngoặc đơn thứ hai, trong trường hợp này là 'fg'.

2

RegEx này có được cấu trúc theo cách như vậy để bỏ qua mục nhập mảng đầu tiên và chỉ tạo ra kết quả mong muốn không?

Tuyệt đối. Sử dụng assertions. regex này:

preg_match_all('/(?<=\^)[^^]*?(?=~)/', $str, $newStr); 

Kết quả trong:

Array 
(
    [0] => Array 
     (
      [0] => Jony 
      [1] => Smith 
      [2] => [email protected] 
     ) 

) 
0

Bất cứ khi nào bạn có vấn đề tưởng tượng chức năng preg_match_all bạn nên sử dụng một đánh giá như preg_match_all tester @ regextester.net

này cho bạn thấy kết quả trong thời gian thực và bạn có thể cấu hình những thứ như thứ tự kết quả, hướng dẫn meta, chụp bù đắp và nhiều thứ khác.

Các vấn đề liên quan