<?php
$input = <<<'EOF'
1....X.......
2..X..X...X....
3X.X...X..X.....
4X....XXXXXX.....
5X..XXX...........
6.....X..........
7.........X....X
8..X......X....X....
9..X......X....X....X...
A....X.....
B.X..X..
C.....
DXXX
EXXX
FXXX
EOF ;
$pattern = '/
^
(?:(?|
(?(5)(?![\s\S]*+\5))
(?!(?!)()())
(?=
(?:
.
(?=
.*+\n
( \3? . )
.*+\n
( \4? . )
)
)*?
X .*+\n
\3
X .*+\n
\4
X
)
()
|
(?(5)(?=[\s\S]*+\5)|(?!))
(?:
.
(?=
.*+\n
( \1? .)
.*+\n
( \2? .)
)
)+?
(?=
(?<=X) .*+\n
(\1)
(?<=X) .*+\n
(\2)
(?<=X)
)
(?=
([\s\S])
[\s\S]*
(. (?(6)\6))
)
){2})+
/xm' ;
echo "Input:\n " , $input ;
function ( $match ) {
return '!' . $match [ 0 ] ;
}
, $input ) ;
echo "\n \n Lines containing at least one match are marked with '!':\n " , $str ;
echo "\n \n This is group 6 for each match. Each subarray represents a
matching line. The amount of characters indicates how many matches there are
in that particular line. You could find out which line this corresponds to
by using PREG_CAPTURE_OFFSET and inspecting group 0 (the entire match)." ;
?>
PD9waHAKCSRpbnB1dCA9IDw8PCdFT0YnCjEuLi4uWC4uLi4uLi4KMi4uWC4uWC4uLlguLi4uCjNYLlguLi5YLi5YLi4uLi4KNFguLi4uWFhYWFhYLi4uLi4KNVguLlhYWC4uLi4uLi4uLi4uCjYuLi4uLlguLi4uLi4uLi4uCjcuLi4uLi4uLi5YLi4uLlgKOC4uWC4uLi4uLlguLi4uWC4uLi4KOS4uWC4uLi4uLlguLi4uWC4uLi5YLi4uCkEuLi4uWC4uLi4uCkIuWC4uWC4uCkMuLi4uLgpEWFhYCkVYWFgKRlhYWApFT0Y7CiAgICAKICAgICRwYXR0ZXJuID0gJy8KICAgIF4gICAgICAgICAgICAgICAgICAgCiAgICAoPzooP3wKICAgICAgKD8oNSkoPyFbXHNcU10qK1w1KSkKICAgICAgKD8hKD8hKSgpKCkpICAgICAgCiAgICAgICg/PQogICAgICAgICg/OgogICAgICAgICAgLiAgICAgICAgICAKICAgICAgICAgICg/PSAgICAgICAgCiAgICAgICAgICAgIC4qK1xuICAgIAogICAgICAgICAgICAoIFwzPyAuICkKICAgICAgICAgICAgLiorXG4gICAgCiAgICAgICAgICAgICggXDQ/IC4gKQogICAgICAgICAgKQogICAgICAgICkqPyAgICAgICAgIAogICAgICAgIFggLiorXG4gICAgIAogICAgICAgIFwzICAgICAgICAgIAogICAgICAgIFggLiorXG4gICAgIAogICAgICAgIFw0ICAgICAgICAgIAogICAgICAgIFggICAgICAgICAgIAogICAgICApCiAgICAgICgpCiAgICB8CiAgICAgICg/KDUpKD89W1xzXFNdKitcNSl8KD8hKSkKICAgICAgKD86CiAgICAgICAgLgogICAgICAgICg/PQogICAgICAgICAgLiorXG4KICAgICAgICAgICggXDE/IC4pCiAgICAgICAgICAuKitcbgogICAgICAgICAgKCBcMj8gLikKICAgICAgICApCiAgICAgICkrPwogICAgICAoPz0KICAgICAgICAoPzw9WCkgLiorXG4gICAgICAgCiAgICAgICAgKFwxKSAgICAgICAgICAgICAgIAogICAgICAgICg/PD1YKSAuKitcbiAgICAgICAKICAgICAgICAoXDIpICAgICAgICAgICAgICAgCiAgICAgICAgKD88PVgpICAgICAgICAgICAgIAogICAgICApCiAgICAgICg/PQogICAgICAgIChbXHNcU10pICAgIAogICAgICAgIFtcc1xTXSoKICAgICAgICAoLiAoPyg2KVw2KSkKICAgICAgKQogICAgKXsyfSkrCiAgICAveG0nOwogICAgCiAgICBlY2hvICJJbnB1dDpcbiIsICRpbnB1dDsKCiAgICAkc3RyID0gcHJlZ19yZXBsYWNlX2NhbGxiYWNrKCRwYXR0ZXJuLCAKICAgICAgICBmdW5jdGlvbigkbWF0Y2gpIHsKICAgICAgICAgICAgcmV0dXJuICchJyAuICRtYXRjaFswXTsKICAgICAgICB9CiAgICAgICAgLCAkaW5wdXQpOwogICAgCiAgICAkc3RyID0gcHJlZ19yZXBsYWNlKCcvXig/ISEpL20nLCAnLScsICRzdHIpOwogICAgCiAgICBlY2hvICJcblxuTGluZXMgY29udGFpbmluZyBhdCBsZWFzdCBvbmUgbWF0Y2ggYXJlIG1hcmtlZCB3aXRoICchJzpcbiIsICRzdHI7CiAgICAKICAgIHByZWdfbWF0Y2hfYWxsKCRwYXR0ZXJuLCAkaW5wdXQsICRtYXRjaGVzKTsKICAgIGVjaG8gIlxuXG5UaGlzIGlzIGdyb3VwIDYgZm9yIGVhY2ggbWF0Y2guIEVhY2ggc3ViYXJyYXkgcmVwcmVzZW50cyBhCiAgICBtYXRjaGluZyBsaW5lLiBUaGUgYW1vdW50IG9mIGNoYXJhY3RlcnMgaW5kaWNhdGVzIGhvdyBtYW55IG1hdGNoZXMgdGhlcmUgYXJlCiAgICBpbiB0aGF0IHBhcnRpY3VsYXIgbGluZS4gWW91IGNvdWxkIGZpbmQgb3V0IHdoaWNoIGxpbmUgdGhpcyBjb3JyZXNwb25kcyB0bwogICAgYnkgdXNpbmcgUFJFR19DQVBUVVJFX09GRlNFVCBhbmQgaW5zcGVjdGluZyBncm91cCAwICh0aGUgZW50aXJlIG1hdGNoKS4iOwogICAgcHJpbnRfcigkbWF0Y2hlc1s2XSk7Cj8+