1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730
|
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- $Revision: 1.30 $ -->
<reference id="ref.pcre">
<title>Expressions régulières compatibles Perl</title>
<titleabbrev>PCRE</titleabbrev>
<partintro>
<para>
La syntaxe des masques utilisés dans ces fonctions ressemble
fort à celle de Perl. Les expressions seront entourées
de délimiteurs, slash (/), par exemple. N'importe quel
caractère peut servir de délimiteur, tant qu'il
n'est pas alpha-numérique ou n'est pas un antislash (\).
Si un délimiteur doit être utilisé dans
l'expression, il faudra l'échapper avec un antislash.
Depuis PHP 4.0.4, vous pouvez utiliser les délimiteurs
(), {}, [], et <>, comme en Perl.
</para>
<para>
Le délimiteur final peut être suivi d'options qui
affecteront la recherche. Voir aussi
<link linkend="pcre.pattern.modifiers">options de recherche</link>.
</para>
<para>
<example>
<title>Exemples de masques valides</title>
<itemizedlist>
<listitem>
<simpara>
<literal>/<\/\w+>/</literal>
</simpara>
</listitem>
<listitem>
<simpara>
<literal>|(\d{3})-\d+|Sm</literal>
</simpara>
</listitem>
<listitem>
<simpara>
<literal>/^(?i)php[34]/</literal>
</simpara>
</listitem>
<listitem>
<simpara>
<literal>{^\s+(\s+)?$}</literal>
</simpara>
</listitem>
</itemizedlist>
</example>
</para>
<para>
<example>
<title>Exemples de masques invalides</title>
<itemizedlist>
<listitem>
<simpara>
/href='(.*)' - délimiteur final manquant
</simpara>
</listitem>
<listitem>
<simpara>
/\w+\s*\w+/J - option 'J' inconnue
</simpara>
</listitem>
<listitem>
<simpara>
1-\d3-\d3-\d4| - délimiteur initial manquant
</simpara>
</listitem>
</itemizedlist>
</example>
</para>
<note>
<simpara>
Les expressions régulières Perl sont disponibles
depuis la PHP 4 et PHP 3.0.9.
</simpara>
<simpara>
Le support des expressions régulières est assuré
par la librairie PCRE, qui est open source, et écrite par Philip
Hazel. Elle est soumise au copyright de l'University of Cambridge,
Angleterre. Elle est disponible à <ulink url="&url.pcre;">&url.pcre;</ulink>.
</simpara>
</note>
</partintro>
<refentry id="function.preg-match">
<refnamediv>
<refname>preg_match</refname>
<refpurpose>Expression régulière standard.</refpurpose>
</refnamediv>
<refsect1>
<title>Description</title>
<methodsynopsis>
<type>int</type><methodname>preg_match</methodname>
<methodparam><type>string</type><parameter>pattern</parameter></methodparam>
<methodparam><type>string</type><parameter>subject</parameter></methodparam>
<methodparam choice="opt"><type>array</type><parameter>matches</parameter></methodparam>
</methodsynopsis>
<para>
<function>preg_match</function> analyse <parameter>subject</parameter>
pour trouver l'expression <parameter>pattern</parameter>.
</para>
<para>
Si <parameter>matches</parameter> est fourni, il sera rempli par
les résultats de la recherche. $matches[0] contiendra le
texte qui satisfait le masque complet, $matches[1] contiendra
le texte qui satisfait la première parenthèse capturante,
etc..
</para>
<para>
<function>preg_match</function> retourne &true; si la
recherche réussit, et &false; sinon (notamment
en cas d'erreur).
</para>
<para>
<example>
<title>Extraction d'un numéro de page d'une chaîne.</title>
<programlisting role="php">
<?php
if (preg_match("/page\s+#(\d+)/i", "Aller à la page numéro 9.", $parts))
print "La page suivante est $parts[1]";
else
print "Page introuvable.";
?>
</programlisting>
</example>
<example>
<title>Trouve le mot "web"</title>
<programlisting role="php">
<?php
// \b, dans le masque, indique une limite de mot, de façon à ce que le mot
// "web" uniquement soit repéré, et pas seulement des parties de mots comme
// dans "webbing" ou "cobweb"
if (preg_match ("/\bweb\b/i", "PHP est le meilleur langage de script du web.")) {
print "Un mot a été trouvé.";
} else {
print "Un mot n'a pas été trouvé.";
}
if (preg_match ("/\bweb\b/i", "PHP est le meilleur langage de script pour les webagency.")) {
print "Un mot a été trouvé.";
} else {
print "Un mot n'a pas été trouvé.";
}
?>
</programlisting>
</example>
<example>
<title>Lire un nom de domaine dans une URL</title>
<programlisting role="php">
<?php
// repérer le nom de l'hôte dans l'URL
preg_match("/^(http:\/\/)?([^\/]+)/i",
"http://www.php.net/index.html", $matches);
$host = $matches[2];
// repérer les deux derniers segments du nom de l'hôte
preg_match("/[^\.\/]+\.[^\.\/]+$/",$host,$matches);
echo "Le nom de domaine est : ".$matches[0]."\n";
?>
</programlisting>
</example>
Cet exemple va afficher :
<computeroutput>
Le nom de domaine est : php.net
</computeroutput>
Voir aussi
<function>preg_match_all</function>,
<function>preg_replace</function> et
<function>preg_split</function>.
</para>
</refsect1>
</refentry>
<refentry id="function.preg-match-all">
<refnamediv>
<refname>preg_match_all</refname>
<refpurpose>Expression régulière globale.</refpurpose>
</refnamediv>
<refsect1>
<title>Description</title>
<methodsynopsis>
<type>int</type><methodname>preg_match_all</methodname>
<methodparam><type>string</type><parameter>pattern</parameter></methodparam>
<methodparam><type>string</type><parameter>subject</parameter></methodparam>
<methodparam><type>array</type><parameter>matches</parameter></methodparam>
<methodparam choice="opt"><type>int</type><parameter>order</parameter></methodparam>
</methodsynopsis>
<para>
<function>preg_match_all</function> analyse <parameter>subject</parameter>
pour trouver l'expression <parameter>pattern</parameter>
et met les résultats dans <parameter>matches</parameter>,
dans l'ordre spécifié par <parameter>order</parameter>.
</para>
<para>
Après avoir trouvé un premier résultat,
la recherche continue jusqu'à la fin de la chaîne.
</para>
<para>
<parameter>order</parameter> peut prendre une des deux valeurs suivantes :
<variablelist>
<varlistentry>
<term>PREG_PATTERN_ORDER</term>
<listitem>
<para>
L'ordre est tel que $matches[0] est un tableau qui
contient les résultats qui satisfont le masque
complet, $matches[1] est un tableau qui contient les
résultats qui satisfont la première
parenthèse capturante, etc..
<informalexample>
<programlisting role="php">
<?php
preg_match_all("|<[^>]+>(.*)</[^>]+>|U", "<b>example: </b><div align=left>a test</div>", $out, PREG_PATTERN_ORDER);
print $out[0][0].", ".$out[0][1]."\n";
print $out[1][0].", ".$out[1][1]."\n";
?>
</programlisting>
</informalexample>
Cet exemple va afficher :
<informalexample>
<literallayout>
<computeroutput>
<b>exemple: </b>, <div align=left>ceci est un test</div>
exemple: , ceci est un test
</computeroutput>
</literallayout>
</informalexample>
Ainsi, $out[0] est un tableau qui contient les résultats qui
satisfont le masque complet, et $out[1] est un tableau qui contient
les balises entre > et <.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>PREG_SET_ORDER</term>
<listitem>
<para>
Les résultats sont classés de telle
façon que $matches[0] contient la première
série de résultat, $matches[1] contient la
deuxième série de résultat, etc...
<informalexample>
<programlisting role="php">
<?php
preg_match_all("|<[^>]+>(.*)</[^>]+>|U", "<b>exemple: </b><div align=left>un test</div>", $out, PREG_SET_ORDER);
print $out[0][0].", ".$out[0][1]."\n";
print $out[1][0].", ".$out[1][1]."\n";
?>
</programlisting>
</informalexample>
Cet exemple va afficher :
<informalexample>
<literallayout>
<computeroutput>
<b>exemple: </b>, exemple:
<div align=left>un test</div>, un test
</computeroutput>
</literallayout>
</informalexample>
Dans ce cas, $matches[0] est la première série de
résultat, et $matches[0][0] contient le texte qui satisfait
le masque complet, $matches[0][1] contient le texte de la
première parenthèse capturante, etc... De même,
$matches[1] contient le texte qui satisfait le masque complet, etc...
</para>
</listitem>
</varlistentry>
</variablelist>
</para>
<para>
Si <parameter>order</parameter> est omis, PREG_PATTERN_ORDER est
utilisé par défaut.
</para>
<para>
<function>preg_match_all</function> retourne le nombre de
résultat qui satisfont le masque complet, ou &false;
en cas d'échec ou d'erreur.
</para>
<para>
<example>
<title>
Extraction de tous les numéros de téléphone d'un texte.
</title>
<programlisting role="php">
<?php
preg_match_all("/\(? (\d{3})? \)? (?(1) [\-\s] ) \d{3}-\d{4}/x",
"Appelez 555-1212 ou 1-800-555-1212", $phones);
?>
</programlisting>
</example>
</para>
<para>
<example>
<title>Recherche les couples de balises HTML (gourmand)</title>
<programlisting role="php">
<?php
// Cet exemple utilise les références arrières (\\2).
// Elles indiquent à l'analyseur qu'il doit trouver quelquechose qu'il
// a déjà repéré un peu plus tôt
// le nombre 2 indique que c'est le deuxième jeu de parenthèses
// capturante qui doit être utilisé (ici, ([\w]+)).
// L'antislash est nécessaire ici, car la chaîne est entre guillemets doubles
$html = "<B>Texte en gras</B><a href=salut.html>clique moi</?>
preg_match_all ("/(<([\w]+)[?>]?>)(.*)(<\/\\?>)/", $html, $matches);
for ($i=0; $i< count($matches[0]); $i++) {
echo "trouvé: ".$matches[0][$i]."\n";
echo "partie 1: ".$matches[1][$i]."\n";
echo "partie 2: ".$matches[3][$i]."\n";
echo "partie 3: ".$matches[4][$i]."\n\n";
}
?>
</programlisting>
</example>
Cet exemple va produire :
<computeroutput>
trouvé: <B>bold text</?>
partie 1: <B>
partie 2: Test en gras
partie 3: </B>
trouvé: <a href=salut.html>clique moi</?>
partie 1: <a href=salut.html>
partie 2: clique moi
partie 3: </?>
</computeroutput>
</para>
<simpara>
Voir aussi
<function>preg_match</function>,
<function>preg_replace</function>
et <function>preg_split</function>.
</simpara>
</refsect1>
</refentry>
<refentry id="function.preg-replace">
<refnamediv>
<refname>preg_replace</refname>
<refpurpose>
Rechercher et remplacer par expression régulière standard.
</refpurpose>
</refnamediv>
<refsect1>
<title>Description</title>
<methodsynopsis>
<type>mixed</type><methodname>preg_replace</methodname>
<methodparam><type>mixed</type><parameter>pattern</parameter></methodparam>
<methodparam><type>mixed</type><parameter>replacement</parameter></methodparam>
<methodparam><type>mixed</type><parameter>subject</parameter></methodparam>
<methodparam choice="opt"><type>int</type><parameter>limit</parameter></methodparam>
</methodsynopsis>
<para>
<function>preg_replace</function> analyse <parameter>subject</parameter>
pour trouver l'expression <parameter>pattern</parameter> et remplace les
résultats par <parameter>replacement</parameter>.
</para>
<para>
<parameter>replacement</parameter> peut contenir des références
de la forme <literal>\\<replaceable>n</replaceable></literal> ou,
depuis PHP 4.0.4) <literal><replaceable>$n</replaceable></literal>.
Cette dernière forme est recommandée. Ces
références seront remplacées par le texte capturé
par la <replaceable>n</replaceable>'-ième parenthèse capturante
du masque. <replaceable>n</replaceable> peut prendre des valeurs de 0 à
99, et <literal>\\0</literal> ou <literal>$0</literal>, correspondent
au texte de qui satisfait le masque complet. Les parenthèses
ouvrantes sont comptées de gauche à droite (en commençant
à 1) pour déterminer le numéro de parenthèse
capturante.
</para>
<para>
Si la recherche n'aboutit à aucun résultat,
<parameter>subject</parameter> sera inchangé.
</para>
<para>
Tous les paramètres de <function>preg_replace</function>
peuvent être des tableaux.
</para>
<para>
Si <parameter>subject</parameter> est un tableau, alors l'opération
sera appliquée à chacun des éléments du
tableau, et le tableau sera retourné.
</para>
<para>
Si <parameter>pattern</parameter> et <parameter>replacement</parameter>
sont des tableaux, alors <function>preg_replace</function> prend une valeur
de chaque tableau, et l'utilise pour faire la recherche et le remplacement.
Si <parameter>replacement</parameter> à moins d'éléments
que <parameter>pattern</parameter>, alors la chaîne vide est
utilisé pour le reste des valeurs. Si <parameter>pattern</parameter>
est un tableau, et que <parameter>replacement</parameter> est une
chaîne, alors cette chaîne sera utilisée pour
chaque valeur de <parameter>pattern</parameter>.
Le contraire n'aurait pas de sens.
</para>
<para>
<literal>/e</literal> force <function>preg_replace</function>
à traiter <parameter>replacement</parameter> comme du
code PHP une fois que les substitutions adéquates ont
été faites. Conseil :assurez-vous que
<parameter>replacement</parameter> est un code PHP valide, car sinon, PHP
trouvera une erreur d'analyse (parse error) dans cette ligne.
</para>
<para>
<literal>/F</literal> indique que le paramètre
<parameter>replacement</parameter> doit être considéré
comme un nom de fonction. Cette fonction sera appelée, avec un
tableau contenant les éléments trouvés comme
arguments. La fonctoin doit retourner la chaine de remplacement. Cette option
a été ajoutée en PHP 4.0.4.
</para>
<para>
<example>
<title>Remplacement de plusieurs valeurs</title>
<programlisting role="php">
<?php
$patterns = array ("/(19|20)(\d{2})-(\d{1,2})-(\d{1,2})/",
"/^\s*{(\w+)}\s*=/");
$replace = array ("\\3/\\4/\\1\\2", "$\\1 =");
print preg_replace ($patterns, $replace, "{startDate} = 1999-5-27");
?>
</programlisting>
</example>
Cet exemple va afficher :
<computeroutput>
$startDate = 5/27/1999
</computeroutput>
<example>
<title>Utilisation de l'option /e </title>
<programlisting role="php">
<?php
preg_replace("/(<\/?)(\w+)([^>]*>/e", "'\\1'.strtoupper('\\2').'\\3'", $html_body);
?>
</programlisting>
<para>
Cela va mettre en majuscule toutes les balises HTML du texte.
</para>
</example>
<example>
<title>Conversion HTML en texte</title>
<programlisting role="php">
<?php
// $document contient un document HTML
// Ce script va effacer les balises HTML, les javascript
// et les espaces. Il remplace aussi quelques entités HTML
// courante en leur équivalent texte.
$search = array ("'<script[?>]*?>.*?</script>'si", // Supprime le javascript
"'<[\/\!]*?[^<?>]*?>'si", // Supprime les balises HTML
"'([\r\n])[\s]+'", // Supprime les espaces
"'&(quot|#34);'i", // Supprime les entites HTML
"'&(amp|#38);'i",
"'&(lt|#60);'i",
"'&(gt|#62);'i",
"'&(nbsp|#160);'i",
"'&(iexcl|#161);'i",
"'&(cent|#162);'i",
"'&(pound|#163);'i",
"'&(copy|#169);'i",
"'&#(\d+);'e"); // Evaluation comme PHP
$replace = array ("",
"",
"\\1",
"\"",
"&",
"<",
?>",
" ",
chr(161),
chr(162),
chr(163),
chr(169),
"chr(\\1)");
$text = preg_replace ($search, $replace, $document);
?>
</programlisting>
</example>
</para>
<note>
<para>
Le paramètre <parameter>limit</parameter> a été ajouté
à partir de PHP 4.0.1pl2.
</para>
</note>
<para>
Voir aussi
<function>preg_match</function>,
<function>preg_match_all</function> et
<function>preg_split</function>.
</para>
</refsect1>
</refentry>
<refentry id="function.preg-replace-callback">
<refnamediv>
<refname>preg_replace_callback</refname>
<refpurpose>Rechercher/remplacer avec fonction de callback</refpurpose>
</refnamediv>
<refsect1>
<title>Description</title>
<methodsynopsis>
<type>mixed</type><methodname>preg_replace_callback</methodname>
<methodparam><type>mixed</type><parameter>pattern</parameter></methodparam>
<methodparam><type>mixed</type><parameter>callback</parameter></methodparam>
<methodparam><type>mixed</type><parameter>subject</parameter></methodparam>
<methodparam choice="opt"><type>int</type><parameter>limit</parameter></methodparam>
</methodsynopsis>
<para>
Le comportement de <function>preg_replace</function> est presque
identique à celui de <function>preg_replace</function>, hormis le fait
qu'à la place du paramètre <parameter>replacement</parameter>, il faut
spécifier une fonction de callback <parameter>callback</parameter>
qui sera appelée, avec les éléments trouvés en arguments.
Cette fonction retourne alors la chaîne de remplacement.
</para>
<para>
<function>preg_replace_callback</function> a été ajoutée
en PHP 4.0.5.
</para>
<para>
Voir aussi <function>preg_replace</function>.
</para>
</refsect1>
</refentry>
<refentry id="function.preg-split">
<refnamediv>
<refname>preg_split</refname>
<refpurpose>
Eclatement d'une chaîne par expression régulière.
</refpurpose>
</refnamediv>
<refsect1>
<title>Description</title>
<methodsynopsis>
<type>array</type><methodname>preg_split</methodname>
<methodparam><type>string</type><parameter>pattern</parameter></methodparam>
<methodparam><type>string</type><parameter>subject</parameter></methodparam>
<methodparam choice="opt"><type>int</type><parameter>limit</parameter></methodparam>
<methodparam choice="opt"><type>int</type><parameter>flags</parameter></methodparam>
</methodsynopsis>
<para>
<function>preg_split</function> retourne un tableau contenant les
sous-chaînes de <parameter>subject</parameter>,
séparées par les chaînes qui vérifient
<parameter>pattern</parameter>.
</para>
<para>
Si <parameter>limit</parameter> est spécifié, alors seules les
<parameter>limit</parameter> premières sous-chaînes sont retournées
et si <parameter>limit</parameter> vaut -1, cela signifie en fait
"sans limite", ce qui est utile pour passer le paramètre
<parameter>flags</parameter>.
</para>
<para>
<parameter>flags</parameter> peut être la combinaison des
options suivantes (combinées avec l'opérateur <literal>|</literal>):
<variablelist>
<varlistentry>
<term>PREG_SPLIT_NO_EMPTY</term>
<listitem>
<simpara>
Si cette option est activée, seules les sous-chaînes non vides
seront retournées par <function>preg_split</function>.
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term>PREG_SPLIT_DELIM_CAPTURE</term>
<listitem>
<simpara>
Si cette option est activée, les expressions entre parenthèses entre
les délimiteurs de masques seront aussi capturées et retournées.
Cette option a été ajoutée en PHP 4.0.5.
</simpara>
</listitem>
</varlistentry>
</variablelist>
</para>
<note>
<para>
Le paramètre <parameter>flags</parameter> a été
ajouté en PHP Beta 3.
</para>
</note>
<para>
<example>
<title>Eclatement d'une chaîne de recherche.</title>
<programlisting role="php">
<?php
// scinde la phrase grâce aux virgules et espacements
// ce qui inclus les " ", \r, \t, \n et \f
$keywords = preg_split ("/[\s,]+/", "langage hypertexte, programmation");
?>
</programlisting>
</example>
</para>
<para>
<example>
<title>Scinder une chaîne en caractères</title>
<programlisting role="php">
<?php
$str = 'string';
$chars = preg_split('//', $str, -1, PREG_SPLIT_NO_EMPTY);
print_r($chars);
?>
</programlisting>
</example>
</para>
<para>
Voir aussi
<function>explode</function>,
<function>spliti</function>,
<function>split</function>,
<function>implode</function>,
<function>preg_match</function>,
<function>preg_match_all</function> et
<function>preg_replace</function>.
</para>
</refsect1>
</refentry>
<refentry id="function.preg-quote">
<refnamediv>
<refname>preg_quote</refname>
<refpurpose>
Echappement des caractères spéciaux des expressions
régulières.
</refpurpose>
</refnamediv>
<refsect1>
<title>Description</title>
<methodsynopsis>
<type>string</type><methodname>preg_quote</methodname>
<methodparam><type>string</type><parameter>str</parameter></methodparam>
<methodparam choice="opt"><type>string</type><parameter>delimiter</parameter></methodparam>
</methodsynopsis>
<para>
<function>preg_quote</function> ajoute un antislash devant tous
les caractères de la chaîne <parameter>str</parameter>.
Cela est très utile si vous avez une chaîne qui va
servir de masque, mais qui est générée durant
l'exécution.
</para>
<para>
Si l'argument optionnel <parameter>delimiter</parameter> est fourni,
il sera aussi échappé. Ceci est pratique pour échapper
le délimiteur requis par les fonctions PCRE. Le slash / est le
délimiteur le plus répandu.
</para>
<para>
Les caractères spéciaux qui seront échappés :
<screen>. \\ + * ? [ ^ ] $ ( ) { } = ! < > | :</screen>
</para>
<para>
<example>
<title>Protège des caractères spéciaux</title>
<programlisting role="php">
<?php
$keywords = "$40 pour un g3/400";
$keywords = preg_quote ($keywords, "/");
echo $keywords; // retourne \$40 pour un g3\/400
?>
</programlisting>
</example>
<example>
<title>Mise en italique d'un mot dans un texte</title>
<programlisting role="php">
<?php
// Dans cet exemple, preg_quote($word) sert à éviter que les astérisques
// prennent une valeur particulière dans l'exepression régulière.
$textbody = "Ce livre est *très* difficile à trouver.";
$word = "*très*";
$textbody = preg_replace ("/".preg_quote($word)."/",
"<B>".$word."</B>",
$textbody);
?>
</programlisting>
</example>
</para>
</refsect1>
</refentry>
<refentry id="function.preg-grep">
<refnamediv>
<refname>preg_grep</refname>
<refpurpose>Retourne un tableau avec les résultat de la recherche.</refpurpose>
</refnamediv>
<refsect1>
<title>Description</title>
<methodsynopsis>
<type>array</type><methodname>preg_grep</methodname>
<methodparam><type>string</type><parameter>pattern</parameter></methodparam>
<methodparam><type>array</type><parameter>input</parameter></methodparam>
</methodsynopsis>
<para>
<function>preg_grep</function> retourne un tableau qui
contient les éléments de <parameter>input</parameter>
qui satisfont le masque <parameter>pattern</parameter>.
</para>
<para>
Depuis PHP 4.0.4, le tableau retourné par <function>preg_grep</function>
est indexé en utilisant les clés issues du tableau
<parameter>input</parameter>. Si ces clés sont inutiles, utilisez
la fonction <function>array_values</function> sur le tableau retourné
par <function>preg_grep</function> pour obtenir le comportement traditionnel.
</para>
<para>
<example>
<title>Exemple avec <function>preg_grep</function></title>
<programlisting role="php">
<?php
// recherche les nombres à virgule flottante
preg_grep("/^(\d+)?\.\d+$/", $array);
?>
</programlisting>
</example>
</para>
</refsect1>
</refentry>
<refentry id="pcre.pattern.modifiers">
<refnamediv>
<refname>options de recherche</refname>
<refpurpose>
Options disponibles pour les expressions régulières.
</refpurpose>
</refnamediv>
<refsect1>
<title>Description</title>
<para>
Les options de PCRE sont listées ci-dessous. Les noms entre
parenthèses sont les noms internes à PCRE.
</para>
<para>
<blockquote>
<variablelist>
<varlistentry>
<term><emphasis>i</emphasis> (PCRE_CASELESS)</term>
<listitem>
<simpara>
Effectue une recherche insensible à la casse.
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis>m</emphasis> (PCRE_MULTILINE)</term>
<listitem>
<simpara>
Par défaut, PCRE traite la chaîne sujet comme une seule
ligne (même si cette chaîne contient des retours chariot).
Le méta-caractère "début de ligne" (^) ne sera
valable qu'une seule fois, au début de la ligne, et le
méta caractère "fin de ligne " ($) ne sera valable
qu'à la fin de la chaîne, ou avant le retour chariot
final (à moins que l'option D ne soit activée). C'est le
même fonctionnement qu'en Perl.
</simpara>
<simpara>
Lorsque cette option est activée, " début de ligne " et
" fin de ligne " correspondront alors aux caractères
suivant et précédent immédiatement un
caractère de nouvelle ligne, en plus du début
et de la fin de la chaîne. C'est le même
fonctionnement que l'option Perl /m. S'il n'y a pas de
caractère de nouvelle ligne "\n" dans la chaîne sujet,
ou s'il n'y a aucune occurrence de ^ ou $ dans le masque, cette option
ne sert à rien.
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis>s</emphasis> (PCRE_DOTALL)</term>
<listitem>
<simpara>
Avec cette option, le méta caractère point (.)
remplace n'importe quel caractère, y compris les nouvelles
lignes. Sans cette option, le caractère point ne remplace
pas les nouvelles lignes. Cette option est équivalente
à l'option Perl /s. Une classe de caractères
négative telle que [^a] acceptera toujours les
caractères de nouvelles lignes, indépendamment
de cette option.
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis>x</emphasis> (PCRE_EXTENDED)</term>
<listitem>
<simpara>
Avec cette option, les caractères d'espacement sont
ignorés, sauf lorsqu'ils sont échappés,
ou à l'intérieur d'une classe de caractères,
et tous les caractères entre # non échappés
et en dehors d'une classe de caractères, et le prochain
caractère de nouvelle ligne sont ignorés. C'est
l'équivalent Perl de l'option /x : elle permet l'ajout
de commentaires dans les masques compliqués. Notez bien,
cependant, que cela ne s'appliquent qu'aux caractères de
données. Les caractères d'espacement ne doivent
jamais apparaître dans les séquences spéciales
d'un masque, comme par exemple dans la séquence (?( qui
introduit une parenthèse conditionnelle.
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis>E</emphasis></term>
<listitem>
<simpara>
Avec cette option, <function>preg_replace</function> effectue la
substitution normale des références arrières dans la
chaîne de remplacement, puis l'évalue comme un code PHP, et
utilise le résultat pour remplacer la chaîne de recherche.
</simpara>
<simpara>
Seule <function>preg_replace</function> utilise cette option. Elle est
ignorée par les autres.
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis>A</emphasis> (PCRE_ANCHORED)</term>
<listitem>
<simpara>
Avec cette option, le masque est ancré de force, c'est-à-dire que le masque doit s'appliquer entre le début
et la fin de la chaîne sujet pour être
considéré comme trouvé. Il est
possible de réaliser le même effet en
ajoutant les méta-caractères adéquats,
ce qui est la seule manière de le faire en Perl.
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis>E</emphasis> (PCRE_DOLLAR_ENDONLY)</term>
<listitem>
<simpara>
Avec cette option, le méta-caractère $ ne sera
valable qu'à la fin de la chaîne sujet. Sans
cette option, $ est aussi valable avant une nouvelle ligne,
si cette dernière est le dernier caractère de
la chaîne. Cette option est ignorée si l'option
<emphasis>m</emphasis> est activée. Il n'y a pas
d'équivalent en Perl.
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis>S</emphasis></term>
<listitem>
<simpara>
Lorsqu'un masque est utilisé plusieurs fois, cela vaut
la peine de passer quelques instants de plus pour l'analyser
et optimiser le code pour accélérer les
traitements ultérieurs. Cette option force cette
analyse plus poussée. Actuellement, cette analyse
n'est utile que pour les masques non ancrés, qui
ne commencent pas par un caractère fixe.
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis>U</emphasis> (PCRE_UNGREEDY)</term>
<listitem>
<simpara>
Cette option inverse la tendance à la gourmandise des
expressions régulières. Vous pouvez aussi inverser
cette tendance au coup par coup avec un ?. De même, si
cette option est activée, le <literal>?</literal> rendra
gourmand une séquence. Cette option n'est pas compatible
avec Perl. Elle peut aussi être mise dans le masque avec
l'option <literal>?U</literal>.
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis>X</emphasis> (PCRE_EXTRA)</term>
<listitem>
<simpara>
Cette option ajoute d'autres fonctionnalités incompatible
avec le PCRE de Perl. Tous les antislash suivis d'une lettre qui
n'aurait pas de signification particulière cause une erreur,
permettant la réservation de ces combinaisons pour des ajouts
fonctionnels ultérieurs. Par défaut, comme en Perl, les
antislash suivis d'une lettre sans signification particulière
sont traités comme des valeurs littérales. Actuellement,
cette option ne déclenche pas d'autres fonctions.
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis>u</emphasis> (PCRE_UTF8)</term>
<listitem>
<simpara>
Cette option inactive les fonctionnalités additionnelles de
PCRE qui ne sont pas compatibles avec Perl. Les chaînes sont
traitées comme des chaînes UTF-8. Cette option est disponible
en PHP 4.1.0 et plus récent.
</simpara>
</listitem>
</varlistentry>
</variablelist>
</blockquote>
</para>
</refsect1>
</refentry>
<refentry id="pcre.pattern.syntax">
<refnamediv>
<refname>syntaxe des masques</refname>
<refpurpose>
Fonctionnement des expressions régulières.
</refpurpose>
</refnamediv>
<refsect1>
<title>Description</title>
<para>
La bibliothèque PCRE est un ensemble de fonctions qui
implémentent la recherche par expressions
régulières, en utilisant la même syntaxe
et la même sémantique que le Perl 5, avec quelques
nuances (voir ci-dessous). L'implémentation actuelle
est celle de Perl 5.005.
</para>
</refsect1>
<refsect1>
<title>Différences avec Perl</title>
<para>
Les différences avec le Perl 5.005 sont présentée ici :
<orderedlist>
<listitem>
<simpara>
Par défaut, un caractère d'espacement correspond à
n'importe quel caractère que la fonction C isspace() reconnaît,
bien qu'il soit possible de recompiler la bibliothèque PCRE avec
d'autres tables de caractères. Normalement, isspace() retourne
&true; pour les espaces, les retours chariot, les
nouvelles lignes, les formfeed, les tabulations verticales et horizontales.
Le Perl 5 n'accepte plus la tabulation verticale comme caractère
d'espacement. La séquence \v qui était dans la documentation
Perl depuis longtemps n'a jamais été reconnue. Cependant, la
tabulation verticale elle-même était reconnue comme un
caractère d'espacement jusqu'à la version 5.002. Avec les
version 5.004 et 5.005, l'option \s l'ignore.
</simpara>
</listitem>
<listitem>
<simpara>
PRCE ne tolère pas la répétition de quantificateurs
dans les expressions. Perl le permet, mais cela ne signifie pas ce que vous
pourriez penser. Par exemple, (?!a){3} ne s'interprète pas : les trois
caractères suivants ne sont pas des "a". En fait, cela
s'interprète comme : le caractère suivant n'est pas "a" trois fois.
</simpara>
</listitem>
<listitem>
<simpara>
Les occurrences de sous-masques qui interviennent dans des assertions
négatives sont comptées, mais elles ne sont pas
enregistrées dans le vecteur d'occurrences. Perl modifie ses
variables numériques pour toutes les occurrences de sous-masque,
avant que l'assertion ne vérifie le masque entier, et uniquement si
les sous-masques ne trouvent qu'une seule occurrence.
</simpara>
</listitem>
<listitem>
<simpara>
Bien que les caractères nul soient tolérés dans la
chaîne de recherche, ils ne sont pas acceptés dans le
masque, car le masque est utilisé comme une chaîne C
standard, terminée par le caractère nul. Il faut donc
utiliser la séquence d'échappement "\0" dans le masque
pour rechercher les caractères nul.
</simpara>
</listitem>
<listitem>
<simpara>
Les séquence d'échappement suivantes ne sont pas
supportées par le Perl: \l, \u, \L, \U, \E,
\Q. En fait, elles sont implémentées par la gestion
intrinsèque de chaînes du Perl, et ne font pas partie
de ses caractères spéciaux.
</simpara>
</listitem>
<listitem>
<simpara>
L'assertion \G du Perl n'est pas supportée car elle n'est pas
pertinente pour faire des recherches avec des masques uniques.
</simpara>
</listitem>
<listitem>
<simpara>
De manière assez évidente, PCRE n'accepte pas la
construction <literal>(?{code})</literal>.
</simpara>
</listitem>
<listitem>
<simpara>
Au moment de l'écriture de PCRE, Perl 5.005_02 avait quelques
comportements étranges avec la capture des chaînes
lorsqu'une partie du masque est redoublée. Par exemple, "aba" avec
le masque /^(a(b)?)+$/ va affecter à $2 la valeur "b", mais la
même manipulation avec "aabbaa" et /^(aa(bb)?)+$/ laissera $2 vide.
Cependant, si le masque est remplacé par /^(aa(b(b))?)+$/ alors $2
(et d'ailleurs $3) seront correctement affectés. Avec le Perl
5.004, $2 sera correctement affecté dans les deux cas, et c'est
aussi vrai avec PCRE. Si Perl évolue vers un autre comportement
cohérent, PCRE s'adaptera probablement.
</simpara>
</listitem>
<listitem>
<simpara>
Une autre différence encore non résolue est le fait qu'en
Perl 5.005_02 le masque /^(a)?(?(1)a|b)+$/ accepte la chaîne "a",
tandis que PCRE ne l'accepte pas. Cependant, que ce soit avec Perl ou
PCRE /^(a)?a/ et "a" laisseront $1 vide.
</simpara>
</listitem>
<listitem>
<para>
PCRE propose quelques extensions aux expressions régulières du Perl.
<orderedlist>
<listitem>
<simpara>
(a) Bien que les assertions avec retour (lookbehind) soit obligée
d'apparier une chaîne de longueur fixe, toutes les assertions avec
retour peuvent avoir une longueur différente. Perl 5.005 leur
impose d'avoir toutes la même longueur.
</simpara>
</listitem>
<listitem>
<simpara>
(b) Si <link linkend="pcre.pattern.modifiers">PCRE_DOLLAR_ENDONLY</link> est
activé, et que <link linkend="pcre.pattern.modifiers">PCRE_MULTILINE</link>
n'est pas activé, le méta caractère
<literal>$</literal> ne s'applique qu'à la fin
physique de la chaîne, et non pas avant les caractères
de nouvelle ligne.
</simpara>
</listitem>
<listitem>
<simpara>
(c) Si <link linkend="pcre.pattern.modifiers">PCRE_EXTRA</link> est
activé, un antislash suivi d'une lettre sans signification
spéciale est considérée comme une erreur.
</simpara>
</listitem>
<listitem>
<simpara>
(d) SI <link linkend="pcre.pattern.modifiers">PCRE_UNGREEDY</link> est
activé, la "gourmandise" des quantificateurs de
répétition est inversées, ce qui est rend non
gourmand par défaut, mais s'ils sont suivis de ?, il seront
gourmands.
</simpara>
</listitem>
</orderedlist>
</para>
</listitem>
</orderedlist>
</para>
</refsect1>
<refsect1 id="regexp.reference">
<title>Détails sur les expressions régulières</title>
<refsect2 id="regexp.introduction">
<title>Introduction</title>
<simpara>
La syntaxe et la sémantique des expressions régulière
supportées par PCRE sont décrites ci-dessous. Les expressions
régulières sont aussi décrites dans la documentation
Perl, et dans un grand nombre d'autres livres, avec de nombreux exemples.
Jeffrey Friedl's "Mastering Regular Expressions", édité
chez O'Reilly (ISBN 1-56592-257-3), les décrits en profondeur.
Cette description est organisée comme une documentation de
référence.
</simpara>
<simpara>
Une expression régulière est un masque, appliqué à
une chaîne sujet, de gauche à droite. La plupart des
caractères se représentent eux-mêmes. Un exemple
trivial : un masque qui serait "<literal>Le rapide renard gris</literal>",
pourra correspondre à une partie de la chaîne sujet qui sera
identique au masque, comme par exemple
"<literal>Le rapide renard gris court dans la forêt</literal>",
</simpara>
</refsect2>
<refsect2 id="regexp.reference.meta">
<title>Méta-caractères</title>
<para>
La puissance des expressions régulières provient de
leur capacité à autoriser des alternatives et des quantificateurs
de répétition dans le masque. Ils sont encodés
dans le masque par des méta-caractères, qui ne représentent
pas ce qu'ils sont, mais sont interprétés d'une certaine
manière.
</para>
<para>
Il y a deux sortes de méta-caractères : ceux qui sont
reconnus n'importe où dans un masque, hormis entre crochets,
et ceux qui sont reconnus entre crochets.
</para>
<para>
A l'extérieur des crochets, les méta caractères sont :
<variablelist>
<varlistentry>
<term><emphasis>/</emphasis> antislash</term>
<listitem>
<simpara>
Caractère d'échappement, avec de multiples usages
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis>^</emphasis> Accent circonflexe</term>
<listitem>
<simpara>
Le début de la chaîne sujet (ou de ligne, en mode multiligne)
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis>$</emphasis> Dollar</term>
<listitem>
<simpara>
La fin de la chaîne sujet (ou de ligne, en mode multiligne)
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis>.</emphasis> Point</term>
<listitem>
<simpara>
Remplace n'importe quel caractère, hormis le caractère
de nouvelle ligne (par défaut) ;
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis>[</emphasis> Crochet ouvrant</term>
<listitem>
<simpara>
Caractère de début de définition de classe
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis>]</emphasis> Crochet fermant</term>
<listitem>
<simpara>
Caractère de fin de définition de classe
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis>|</emphasis> Barre verticale</term>
<listitem>
<simpara>
Caractère de début d'alternative
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis>(</emphasis> Parenthèse ouvrante</term>
<listitem>
<simpara>
Caractère de début de sous-masque
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis>)</emphasis> Parenthèse fermante</term>
<listitem>
<simpara>
Caractère de fin de sous-masque
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis>?</emphasis> Point d'interrogation</term>
<listitem>
<simpara>
Etend le sens de (; quantificateur de 0 ou 1; quantificateur de minimisation
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis>*</emphasis> Etoile</term>
<listitem>
<simpara>
Quantificateur de 0 ou plus
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis>+</emphasis> Plus</term>
<listitem>
<simpara>
Quantificateur de 1 ou plus
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis>{</emphasis> Accolade ouvrante</term>
<listitem>
<simpara>
Caractère de début de quantificateur minimum/maximum
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis>}</emphasis> Accolade fermante</term>
<listitem>
<simpara>
Caractère de fin de quantificateur minimum/maximum
</simpara>
</listitem>
</varlistentry>
</variablelist>
</para>
<para>
La partie du masque qui est entourée de crochet et appelé
une classe de caractères. Dans les classes de caractères,
les seuls méta caractères autorisés sont :
<variablelist>
<varlistentry>
<term><emphasis>\</emphasis> Antislash</term>
<listitem>
<simpara>
Caractère d'échappement, avec de multiples usages
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis>^</emphasis> Accent circonflexe</term>
<listitem>
<simpara>
Négation de la classe, mais uniquement si placé tout
au début de la classe
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis>-</emphasis> Moins</term>
<listitem>
<simpara>
Indique un intervalle de caractères
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis>]</emphasis> Crochet fermant</term>
<listitem>
<simpara>
Termine la classe de caractères
</simpara>
</listitem>
</varlistentry>
</variablelist>
La section suivante décrit l'utilisation de chaque
méta-caractères.
</para>
</refsect2>
<refsect2 id="regexp.reference.antislash">
<title>Antislash</title>
<para>
Le caractère antislash a de nombreuses utilisations.
</para>
<para>
En premier lieu, s'il est suivi d'un caractère non
alpha-numérique, il ne prendra pas la signification
spéciale qui y est rattachée. Cette utilisation de
l'antislash comme caractère d'échappement s'applique
à l'intérieur et à l'extérieur des
classes de caractères. Par exemple, pour recherche le
caractère étoile "<literal>*</literal>", il faut
écrire dans le masque : "<literal>\*</literal>". Cela
s'applique dans tous les cas, que le caractère qui suive
soit un méta-caractère ou non. C'est un moyen sûr
pour s'assurer qu'un caractère sera recherché
pour sa valeur littérale, plutôt que pour sa valeur
spéciale. En particulier, pour rechercher les antislash,
il faut écrire : "<literal>\\</literal>".
</para>
<para>
Si un masque est utilisé avec l'option
<link linkend="pcre.pattern.modifiers">PCRE_EXTENDED</link>,
les espaces blancs du masque, mais qui ne sont pas dans une
classe de caractères, et les caractères entre dièses
"<literal>#</literal>", ainsi que les nouvelles lignes sont ignorées.
L'antislash peut être utilisé pour échapper et ainsi
rechercher un espace ou un dièse.
</para>
<para>
La deuxième utilité de l'antislash est de pouvoir
coder des caractères invisibles dans les masques. Il n'y
a pas de restriction sur la place de ces caractères
invisibles, hormis pour le caractère nul qui doit terminer
le masque.
</para>
<para>
Lors de la préparation du masque, il est souvent plus pratique
d'utiliser les séquences d'échappement suivantes,
plutôt que le caractère binaire qu'elle représente :
<variablelist>
<varlistentry>
<term><emphasis>\a</emphasis></term>
<listitem>
<simpara>
alarme, c'est-à-dire le caractère BEL (hex 07)
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis>\cx</emphasis></term>
<listitem>
<simpara>
"control-x", avec x qui peut être n'importe quel
caractère.
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis>\e</emphasis></term>
<listitem>
<simpara>
escape (hex 1B)
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis>\f</emphasis></term>
<listitem>
<simpara>
formfeed (hex 0C)
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis>\n</emphasis></term>
<listitem>
<simpara>
nouvelle ligne (hex 0A)
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis>\r</emphasis></term>
<listitem>
<simpara>
retour chariot (hex 0D)
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis>\t</emphasis></term>
<listitem>
<simpara>
tabulation (hex 09)
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis>\xhh</emphasis></term>
<listitem>
<simpara>
caractère en hexadécimal, de code hh
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis>\ddd</emphasis></term>
<listitem>
<simpara>
caractère en octal, de code ddd, ou référence
arrière
</simpara>
</listitem>
</varlistentry>
</variablelist>
</para>
<para>
Dans la séquence "<literal>\cx</literal>" si "<literal>x</literal>"
est en minuscule, il est converti en majuscule. Puis, le bit 6 (hex 40)
est inversé. Ainsi "<literal>\cz</literal>" devient <literal>1A</literal>,
mais "<literal>\c{</literal>" devient hex 3B, tandis que "<literal>\c;</literal>"
devient hex 7B.
</para>
<para>
Après "<literal>\x</literal>", deux caractères
hexadécimaeux sont lus (les lettres peuvent être en majuscule
ou minuscule).
</para>
<para>
Après "<literal>\0</literal>", deux caractères octal sont lus.
Dans chacun des cas, le méta-caractère tente de lire autant
de caractère que possible. Ainsi la séquence
"<literal>\0\x\07</literal>", sera comprise comme deux caractères nuls,
suivi d'un caractère alarme (BEL). Assurez-vous que vous fournissez
suffisamment de chiffres après le méta-caractère.
</para>
<para>
La gestion de la séquence "<literal>\y</literal>", avec y <> 0
est plutôt compliquée. En dehors des caractères de classes,
PCRE va lire y et tous les caractères qui suivent comme des chiffres
décimaux. Si y est plus petit que 10, ou bien s'il y a
déjà eu au moins autant de parenthèses ouvrantes
auparavant, la séquence est prise pour une référence
arrière. Le détail sera vu ultérieurement, après la
section sur les sous-masques.
</para>
<para>
A l'intérieur d'un caractère de classe, ou si y est plus
grand que 10, et qu'il n'y a pas eu assez de parenthèses ouvrantes
auparavant, PCRE lis jusqu'à 3 chiffres octals à la suite
de l'antislash, et génère un octet unique, à partir
des 8 bits de poids faible de la séquence. Tous les chiffres qui
suivent ne sont pas interprétés, et se representent
eux-mêmes. Par exemple:
<variablelist>
<varlistentry>
<term><emphasis>\040</emphasis></term>
<listitem>
<simpara>
une autre manière d'écrire un espace
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis>\40</emphasis></term>
<listitem>
<simpara>
identique, dans la mesure où il n'y a pas 40
parenthèses ouvrantes auparavant
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis>\7</emphasis></term>
<listitem>
<simpara>
est toujours une référence arrière
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis>\11</emphasis></term>
<listitem>
<simpara>
peut être une référence de retour,
ou une tabulation
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis>\011</emphasis></term>
<listitem>
<simpara>
toujours une tabulation
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis>\0113</emphasis></term>
<listitem>
<simpara>
est une tabulation suivi du caractère "3"
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis>\113</emphasis></term>
<listitem>
<simpara>
est le caractère 113 (étant donné qu'il ne
peut y avoir plus de 99 références arrières)
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis>\377</emphasis></term>
<listitem>
<simpara>
est un octet dont tous les bits sont à 1
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis>\0113</emphasis></term>
<listitem>
<simpara>
peut être soit une référence arrière,
soit le caractère &null;, suivi des caractères "8" et "1"
</simpara>
</listitem>
</varlistentry>
</variablelist>
</para>
<para>
Les valeurs octales supérieures ou égales à 100 ne
doivent pas être introduites par un 0, car seuls les trois premiers
octets seront lus.
</para>
<para>
Toutes les séquences qui définissent une valeur d'un seul
octet peuvent être utilisé dans les classes de caractères,
et à l'extérieur. De plus, dans une classe de caractères,
la séquence "<literal>\b</literal>" est interprétée
comme un caractère effacer (backspace, hex 08). A l'extérieur
d'une classe de caractères, il peut avoir d'autres significations
(voir ci-dessous).
</para>
<para>
On peut encore se servir de l'antislash pour préciser des types
génériques de valeurs :
<variablelist>
<varlistentry>
<term><emphasis>\d</emphasis></term>
<listitem>
<simpara>
tout caractère décimal
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis>\D</emphasis></term>
<listitem>
<simpara>
tout caractère qui n'est pas un caractère décimal
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis>\S</emphasis></term>
<listitem>
<simpara>
tout caractère blanc
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis>\s</emphasis></term>
<listitem>
<simpara>
tout caractère qui n'est pas un caractère blanc
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis>\W</emphasis></term>
<listitem>
<simpara>
tout caractère de "mot"
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis>\w</emphasis></term>
<listitem>
<simpara>
tout caractère qui n'est pas un caractère de "mot"
</simpara>
</listitem>
</varlistentry>
</variablelist>
</para>
<para>
Chaque paire précédente définit une partition de
la table des caractères : les deux ensembles sont disjoints.
Un caractère satisfera soit un méta-caractère,
soit l'autre.
</para>
<para>
Un caractère de "mot" sera une lettre, un chiffre ou le
caractère souligné, c'est-à-dire un
caractère qui pourra être une partie d'un mot Perl. La
définition des lettres et chiffres est définie par les
tables de caractères de PCRE, et peut varier suivant la table
locale de caractère (voir "Tables de caractères locales ",
ci-dessus. Par exemple, dans la configuration français ("fr"),
certains caractères ont des codes supérieurs à
128, pour les caractères accentués, et ils seront compris
par le méta caractère <literal>\w</literal>.
</para>
<para>
Ces séquences de caractères peuvent apparaître à
l'intérieur ou à l'extérieur des classes de
caractères. Elles remplacent à chaque fois un
caractère du type correspondant. Si cette séquence est
placée en fin de masque, et qu'il n'y a plus de caractère à
comparer dans la chaîne sujet, la recherche échoue.
</para>
<para>
La quatrième utilisation de l'antislash intervient lors d'assertions
simples. Une assertion impose une condition à un certain point,
sans remplacer de caractère. L'utilisation de sous-masques pour
réaliser des assertions plus complexes est décrites
plus-bas. Les assertions avec antislash sont les suivantes :
<variablelist>
<varlistentry>
<term><emphasis>\b</emphasis></term>
<listitem>
<simpara>
limite de mot
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis>\B</emphasis></term>
<listitem>
<simpara>
pas limite de mot
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis>\A</emphasis></term>
<listitem>
<simpara>
début de la chaîne sujet
(indépendant du mode multi-lignes)
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis>\Z</emphasis></term>
<listitem>
<simpara>
fin de la chaîne sujet ou nouvelle ligne à
la fin de la chaîne sujet
(indépendant du mode multi-lignes)
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis>\z</emphasis></term>
<listitem>
<simpara>
fin de la chaîne sujet
(indépendant du mode multi-lignes)
</simpara>
</listitem>
</varlistentry>
</variablelist>
</para>
<para>
Ces assertions ne peuvent pas apparaître dans une classe de
caractères (mais "\b" a une autre signification à
l'intérieur d'une classe de caractères).
</para>
<para>
Une limite de mot est un emplacement dans la chaîne sujet ou un
caractère et son suivant ne sont pas en même temps des
caractères de mot, ou le contraire (on peut le voir comme
<literal>\w\W</literal> ou <literal>\W\w</literal>), ou encore le
premier ou le dernier caractère est un caractère mot.
</para>
<para>
Les assertions <literal>\A</literal>, <literal>\Z</literal>, et
<literal>\z</literal> diffèrent des méta caractères
<literal>^</literal> et <literal>$</literal> dans la mesure où
ils ne sont pas dépendants des options, notamment
<link linkend="pcre.pattern.modifiers">PCRE_NOTBOL</link>
ou <link linkend="pcre.pattern.modifiers">PCRE_NOTEOL</link>.
La différence entre <literal>\Z</literal> et
<literal>\z</literal> tient au fait que <literal>\Z</literal> recherche
les positions avant les nouvelles lignes et à la fin de la
chaîne sujet, tandis que <literal>\z</literal> ne recherche
que la fin de la chaîne.
</para>
</refsect2>
<refsect2 id="regexp.reference.circudollar">
<title>Accent circonflexe et Dollar</title>
<para>
En dehors d'une classe de caractères, avec les options par
défaut, <literal>^</literal> est une assertion qui n'est
vraie que si elle est placée tout au début de la
chaîne. A l'intérieur d'une classe de caractères,
<literal>^</literal> a un tout autre sens (voir ci-dessous).
</para>
<para>
<literal>^</literal> n'a pas besoin d'être le premier
caractère du masque, si plusieurs alternatives sont
proposées, mais il doit être placé en
premier dans chaque alternative. Si toutes les alternatives
commencent par <literal>^</literal>, alors le masque est dit ancré
(il y a une autre construction qui porte cette appellation).
</para>
<para>
<literal>$</literal> est une assertion qui n'est vraie que si elle
est placée tout en fin de chaîne ou juste avant un
caractère de nouvelle ligne qui serait le dernier
caractère de la chaîne. A l'intérieur d'une
classe de caractères, <literal>$</literal> a un tout autre
sens (voir ci-dessous).
</para>
<para>
<literal>$</literal> n'a pas besoin d'être le dernier
caractère du masque, si plusieurs alternatives sont
proposées, mais il doit être placé en dernier
dans chaque alternative. Si toutes les alternatives finissent par
<literal>$</literal>, alors le masque est dit ancré (il y
a une autre construction qui porte cette appellation). <literal>$</literal>
n'a pas de valeur particulière dans une classe de
caractères.
</para>
<para>
La signification de <literal>$</literal> peut changer, de manière
à l'amener à ce qu'il ne puisse se trouver qu'en toute
fin de la chaîne sujet. Cela se fait en ajoutant l'option
<link linkend="pcre.pattern.modifiers">PCRE_DOLLAR_ENDONLY</link>
au moment de la compilation, ou de l'exécution.
Cette option est inopérante sur <literal>\Z</literal>.
</para>
<para>
La signification de <literal>^</literal> peut changer, de manière
à l'amener à ce qu'il puisse se trouver immédiatement
avant et immédiatement après un caractère de nouvelle
ligne "<literal>\n</literal>". Cela se fait en ajoutant l'option
<link linkend="pcre.pattern.modifiers">PCRE_MULTILINE</link> au moment de
la compilation ou de l'exécution.
Par exemple, le masque <literal>/^abc$/</literal> accepte la chaîne
"<literal>def\nabc</literal>" uniquement en mode multi-lignes. Par
conséquent, toutes les parties du masques qui commencent par
"<literal>^</literal>" ne sont pas ancrées, en mode multi-lignes.
L'option <link linkend="pcre.pattern.modifiers">PCRE_DOLLAR_ENDONLY</link>
est ignorée si l'option
<link linkend="pcre.pattern.modifiers">PCRE_MULTILINE</link> est choisie.
</para>
<para>
Notez que les méta caractères <literal>\A</literal>,
<literal>\Z</literal>, et <literal>\z</literal> peuvent servir à
répérer le début et la fin du sujet, et toutes les
parties du masque qui commenceront par <literal>\A</literal> seront toujours
ancrées, avec l'option
<link linkend="pcre.pattern.modifiers">PCRE_MULTILINE</link> ou non.
</para>
</refsect2>
<refsect2 id="regexp.reference.dot">
<title>Point</title>
<simpara>
En dehors d'une classe de caractères, un point remplace n'importe
quel caractère, même invisible et à l'exception du
caractère de nouvelle ligne. Avec l'option
<link linkend="pcre.pattern.modifiers">PCRE_DOTALL</link> le point
remplace n'importe quel caractère, même le caractère de
nouvelle ligne. La gestion des points et complètement
indépendante de <literal>^</literal> et <literal>$</literal>.
Le seul point commun est que les deux ont un comportement particulier vis
à vis des caractère de nouvelle ligne.
</simpara>
<simpara>
Le point n'a pas de comportement particulier dans une classe de
caractères.
</simpara>
</refsect2>
<refsect2 id="regexp.reference.squarebrackets">
<title>Crochets</title>
<para>
Un crochet ouvrant <literal>[</literal> introduit une classe de
caractères, et le crochet fermant <literal>]</literal>la
conclut. Le crochet fermant n'a pas de signification en lui-même.
Si le crochet fermant est nécessaire à l'intérieur
d'une classe de caractères, il faut qu'il soit le premier
caractère (après un <literal>^</literal> éventuel)
ou échappé avec un antislash.
</para>
<para>
Une classe de caractères remplace un seul caractère
dans la chaîne sujet, à moins que le premier
caractère de la classe soit un accent circonflexe
<literal>^</literal>, qui représente une négation :
le caractère ne doit pas se trouver dans la classe. Si
<literal>^</literal> est nécessaire dans la classe, il
suffit qu'il ne soit pas le premier caractère, ou bien
qu'il soit échappé avec un antislash.
</para>
<para>
Par exemple, le caractère <literal>[aeiou]</literal> remplace
n'importe quelle voyelle minuscule, tandis que <literal>[^aeiou]</literal>
remplace n'importe quelle caractère qui n'est pas une voyelle
minuscule. <literal>^</literal> est une notation pratique pour
spécifier des caractères qui sont dans une classe,
en ne citant que ceux qui n'y sont pas. Le comportement est inchangé.
</para>
<para>
Avec l'option d'insensibilité à la casse, toutes les lettres
d'une classe de caractères représentent en même temps
la majuscule et la minuscule. Par exemple, <literal>[aeiou]</literal>
représentera "<literal>A</literal>" ou "<literal>a</literal>", et
<literal>[^aeiou]</literal> n'acceptera pas ni "<literal>A</literal>",
tandis que sans l'option, elle l'accepterait.
</para>
<para>
Le caractère de nouvelle ligne n'est pas traité de
manière spéciale dans les classes de caractères,
quelque soit l'option <link linkend="pcre.pattern.modifiers">PCRE_DOTALL</link>
ou <link linkend="pcre.pattern.modifiers">PCRE_MULTILINE</link>. Une classe
telle que <literal>[^a]</literal> acceptera toujours une nouvelle ligne.
</para>
<para>
Le signe moins (<literal>-</literal>) est utilisé pour
spécifier un intervalle de caractères, dans
une classe. Par exemple, <literal>[d-m]</literal> remplace toutes
les lettres entre d et m inclus. Si le caractère moins est
requis dans une classe, il faut l'échapper avec un antislash,
ou le faire apparaître à une position ou il ne pourra
pas être interprété comme une indication d'intervalle,
c'est-à-dire au début ou à la fin de la classe.
</para>
<para>
Il n'est pas possible d'avoir le caractère crochet fermant
"<literal>]</literal>" comme fin d'intervalle. Un masque tel que
<literal>[W-]46]</literal> est compris comme la classe de caractères
contenant deux caractères ("W" et "-") suivi de la chaîne
littérale "46]", ce qui fait qu'il va accepter
"<literal>W46]</literal>" ou "<literal>-46]</literal>". Cependant, si
"<literal>]</literal>" est échappé avec un antislash, le
masque <literal>[W-\]46]</literal> est interprété comme
une classe d'un seul caractère, contenant un intervalle de
caractères.
</para>
<para>
La valeur octale ou hexadécimale de "<literal>]</literal>" peut
aussi être utilisée pour déterminer les limites
de l'intervalle. Les intervalles travaillent sur des
séquences ASCII. Ils peuvent aussi être
précisées avec des valeurs numériques, par exemple
"<literal>[\000-\037]</literal>".
Si cet intervalle inclut des lettres utilisées avec une
option d'insensibilité de casse, les majuscules ou minuscules
correspondantes seront aussi incluses. Par exemple,
"<literal>[C-c]</literal>" est équivalent é
"<literal>[][\^_`wxyzabc]</literal>", avec l'option
d'insensibilité de casse. Si la table locale de
caractères est "fr", "<literal>[\xc8-\xcb]</literal>"
correspond aux caractères accentués.
</para>
<para>
Les types de caractères <literal>\d</literal>,
<literal>\D</literal>, <literal>\S</literal>, <literal>\s</literal>,
<literal>\w</literal>, <literal>\W</literal> peuvent aussi intervenir
dans les classes de caractères. Par exemple,
"<literal>[][\^_`wxyzabc][\dABCDEF]</literal>" acceptera n'importe
quel caractère hexadécimal. Un accent circonflexe peut
aussi être utilisé pour spécifier adroitement
des ensembles de caractères plus restrictifs : par exemple
<literal>[^\W_]</literal> accepte toutes les lettres et les chiffres,
mais pas les soulignés. Tous les caractères non alpha-
numériques autres que <literal>\, -, ^</literal> (placés
en début de chaîne) et <literal>]</literal> n'ont pas de
signification particulière, mais ils ne perdront rien à
être échappés.
</para>
</refsect2>
<refsect2 id="regexp.reference.verticalbar">
<title>Barre verticale</title>
<para>
La barre verticale <literal>|</literal> sert à séparer des
alternatives. Par exemple, dans le masque "<literal>/dupont|martin/</literal>"
recherche soit "<literal>dupont</literal>", soit "<literal>martin</literal>".
Le nombre d'alternatives n'est pas limité, et il est même possible
d'utiliser la chaîne vide. Lors de la recherche, toutes les alternatives
sont essayées, de gauche à droite, et la première qui est
acceptée est utilisée.
</para>
<para>
Si les alternatives sont dans un sous-masque, elle ne réussiront
que si le masque principal réussi aussi.
</para>
</refsect2>
<refsect2 id="regexp.reference.internal_options">
<title>Options internes</title>
<para>
Les options <link linkend="pcre.pattern.modifiers">PCRE_CASELESS</link>,
<link linkend="pcre.pattern.modifiers">PCRE_MULTILINE</link>,
<link linkend="pcre.pattern.modifiers">PCRE_DOTALL</link> et
<link linkend="pcre.pattern.modifiers">PCRE_EXTENDED</link> peuvent
être changée à l'intérieur du masque
lui-même, avec des séquences mises entre
"<literal>(?</literal>" et "<literal>)</literal>".
Les options sont :
<variablelist>
<varlistentry>
<term><emphasis>i</emphasis></term>
<listitem>
<simpara>
PCRE_CASELESS
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis>m</emphasis></term>
<listitem>
<simpara>
PCRE_MULTILINE
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis>s</emphasis></term>
<listitem>
<simpara>
PCRE_DOTALL
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis>x</emphasis></term>
<listitem>
<simpara>
PCRE_EXTENDED
</simpara>
</listitem>
</varlistentry>
</variablelist>
Par exemple, <literal>(?im)</literal> rend le masque insensible à
la casse, et multi-lignes. Il est possible d'annuler ces options en les
faisant précéder par un signe <literal>-</literal> : par
exemple <literal>(?im-sx)</literal>, ajoutera les options
<link linkend="pcre.pattern.modifiers">PCRE_CASELESS</link>
et <link linkend="pcre.pattern.modifiers">PCRE_MULTILINE</link> mais
annulera les options <link linkend="pcre.pattern.modifiers">PCRE_DOTALL</link>
et <link linkend="pcre.pattern.modifiers">PCRE_EXTENDED</link>.
Si une option apparaît avant et après le signe moins, l'option
sera annulée.
</para>
<para>
Le domaine d'application de ces options dépend de la position de
la séquence d'option. Pour toutes les séquences d'options
qui sont hors des sous-masques (définis plus loin), l'effet est le
même que si l'option avait été fixée dès
le début de la recherche. Les exemples suivants se comportent tous
de la même façons : <literal>(?i)abc</literal>,
<literal>a(?i)bc</literal>, <literal>ab(?i)c</literal>,
<literal>abc(?i)</literal>, et sont parfaitement équivalents au
masque <literal>abc</literal> avec l'option
<link linkend="pcre.pattern.modifiers">PCRE_CASELESS</link>. En d'autres
termes, activer des séquences d'options dans le corps principal
du masque revient à appliquer l'option à tout le masque, sauf
ordre contraire dans les sous-masques. S'il y a plusieurs séquences
d'options qui portent sur la même option, la dernière s'appliquera.
</para>
<para>
Si une option intervient dans un sous-masque, le comportement est différent.
C'est un changement de comportement apparu en Perl 5.005. Une option à
l'intérieur d'un sous-masque n'affecte que cette partie du masque, ce
qui fait que <literal>(a(?i)b)c</literal> acceptera <literal>abc</literal>
et <literal>aBc</literal> mais aucune autre chaîne (en supposant que
<link linkend="pcre.pattern.modifiers">PCRE_CASELESS</link> n'est pas
utilisé). Cela signifie que les options permettent d'avoir
différente configuration de recherche pour différentes
parties du masque.
</para>
<para>
Une séquence d'options dans une alternative affecte toute
l'alternative. Par exemple : <literal>(a(?i)b|c)</literal> accepte
"<literal>ab</literal>", "<literal>aB</literal>", "<literal>c</literal>",
et "<literal>C</literal>", même si, comme dans le cas de
"<literal>C</literal>", la première alternative qui porte
l'option n'est pas prise en compte. Sinon, cela risque d'introduire
des comportements très étranges : les options
spécifiques à PCRE telles que
<link linkend="pcre.pattern.modifiers">PCRE_UNGREEDY</link> et
<link linkend="pcre.pattern.modifiers">PCRE_EXTRA</link> peuvent
être modifiées de la même
manière, en utilisant respectivement les caractères
U et X. L'option <literal>(?X)</literal> est particulière,
car elle doit toujours intervenir avant toutes les autres options,
même au niveau du masque entier. Il vaut mieux l'activer au
début du masque.
</para>
</refsect2>
<refsect2 id="regexp.reference.subpatterns">
<title>Sous-masques</title>
<para>
Les sous-masques sont délimités par des parenthèses,
et peuvent être imbriquées. Ajouter des sous-masques a deux
utilités :
</para>
<para>
1. Délimiter des alternatives. Par exemple, le masque
<literal>char(don|mant|)</literal> acceptera les mots
"<literal>char</literal>", "<literal>charmant</literal>", ou
"<literal>charmant</literal>". Sans les parenthèses, il
n'accepterait que "<literal>chardon</literal>",
"<literal>mant</literal>" ou la chaîne vide "".
</para>
<para>
2. Le sous-masque est considéré comme capturant : lorsqu'une
chaîne sujet est acceptée par le masque complet, les
sous-masques sont transmis à l'appelant grâce à
un vecteur de sous-masques. Les parenthèses ouvrantes sont
comptées de gauche à droite, (commençant à 1).
Par exemple, soit la chaîne sujet "<literal>le roi soleil</literal>"
qui est utilisée avec le masque suivant :
<literal>Le ((roi|prince) (soleil|charmant))</literal> les sous-masques
capturé sont "<literal>roi soleil</literal>", "<literal>roi</literal>",
et "<literal>soleil</literal>", numérotés respectivement 1, 2, et 3.
</para>
<para>
L'ubiquité des parenthèses n'est pas toujours simple
d'emploi. Il y a des moments où regrouper des sous-masques
est nécessaire, sans pour autant capturer la valeur trouvée.
Si une parenthèse ouvrante est suivie de "<literal>?:</literal>",
le sous-masque ne capture pas la chaîne assortie, et ne sera pas
compté lors de la numérotation des captures. Par exemple,
avec la chaîne "<literal>le prince charmant</literal>", utilisé
avec le masque <literal>Le (( ?roi|prince) (soleil|charmant))</literal>
les chaînes capturées seront "<literal>prince charmant</literal>"
et "<literal>charmant</literal>", numérotés respectivement 1
et 2.
</para>
<para>
Le nombre maximal de chaîne capturées est de 99, et le
nombre total de sous-masque (capturant ou non) ne doit pas
dépasser 200.
</para>
<para>
<literal>(?i:samedi|dimanche)</literal> et
<literal>(?:(?i) samedi | dimanche)</literal> : De plus, comme les
séquences d'options sont valables sur toute une alternative,
les masques ci-dessus accepteront aussi bien "DIMANCHE" que "Dimanche".
</para>
</refsect2>
<refsect2 id="regexp.reference.repetitions">
<title>Répétitions</title>
<para>
Les répétitions sont spécifiées avec
des quantificateurs, qui peuvent être placés à
la suite des caractères suivants :
<variablelist>
<varlistentry>
<term><emphasis>a</emphasis></term>
<listitem>
<simpara>
Un caractère unique, même s'il s'agit
d'un méta caractère
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis>[abc]</emphasis></term>
<listitem>
<simpara>
Une classe de caractères
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis>\2</emphasis></term>
<listitem>
<simpara>
Une référence de retour (Voir section suivante)
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis>(a|b|c)</emphasis></term>
<listitem>
<simpara>
Un sous-masque avec parenthèses (à moins que ce ne soit
une assertion, voir plus loin)
</simpara>
</listitem>
</varlistentry>
</variablelist>
</para>
<para>
Les quantificateurs généraux précisent un nombre
minimum et maximum de répétitions possibles, donnés
par deux nombres entre accolades, et séparés par une virgule.
Ces nombres doivent être plus petits que 65536, et le premier nombre
doit être égal ou inférieur au second. Par exemple
<literal>z{2,4}</literal> accepte "<literal>zz</literal>",
"<literal>zzz</literal>", ou "<literal>zzzz</literal>". L'accolade fermante
n'a pas de signification par elle-même.
</para>
<para>
Si le second nombre est omis, mais que la virgule est là, cela
signifie qu'il n'y a pas de limite supérieure. Si le second nombre
et la virgule sont omis, le quantificateur correspond au nombre exact de
répétition attendues. Par exemple :
accepte n'importe quelle succession d'au moins 3 voyelles minuscules, tandis
que <literal>\d{d}</literal> n'accepte que 8 chiffres exactement.
</para>
<para>
Une accolade ouvrante qui apparaît à une position où
un quantificateur n'est pas accepté, ou si la syntaxe des
quantificateurs n'est pas respectée, sera considérée
littérale. Par exemple, "<literal>{,6}</literal>" n'est pas un
quantificateur, mais une chaîne de 4 caractères.
</para>
<para>
Le quantificateur {0} est autorisé, mais l'expression est alors
ignorée.
<variablelist>
<varlistentry>
<term><emphasis>*</emphasis></term>
<listitem>
<simpara>
équivalent à {0,}
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis>+</emphasis></term>
<listitem>
<simpara>
équivalent à {1,}
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis>?</emphasis></term>
<listitem>
<simpara>
équivalent à {0,1}
</simpara>
</listitem>
</varlistentry>
</variablelist>
</para>
<para>
Il est possible de constituer des boucles infinies en créant un sous-masque
sans caractères, mais pourvu d'un quantificateur sans limite
supérieure. Par exemple "<literal>(a?)*</literal>.
</para>
<para>
Les versions plus anciennes de Perl et PCRE généraient alors
une erreur au moment de la compilation. Cependant, étant donné
qu'il existe des situations où ces constructions peuvent être
utiles, ces masques sont désormais autorisés. Cependant, si
la répétion du sous-masque ne trouve aucun caractère,
la boucle est interrompue.
</para>
<para>
Par défaut, les quantificateurs sont dits "gourmands", c'est à
dire, qu'ils cherchent d'abord à trouve le nombre maximal de
répétitions qui autorise le succès de la recherche.
L'exemple classique posé par cette gourmandise est la recherche de
commentaires d'un programme en C. Les commentaires apparaissent entre les
séquences <literal>/*....*/</literal> et à l'intérieur
de ces délimiteurs, les <literal>*</literal> et <literal>/</literal>
sont autorisés. Appliquer le masque <literal>/\*.*\*/</literal>
à la chaîne
<literal>/* first commet */ not comment /* second comment */</literal>
ne peut réussir, car le masque travaille sur toute la chaîne,
à cause de la gourmandise du caractère <literal>.*</literal>.
</para>
<para>
Cependant, un quantificateur suivi d'un point d'interrogation cesse
d'être gourmand, et au contraire, ne recherche que le nombre
minimum de répétition. Dans ces conditions, le masque
<literal>/\*.*?\*/</literal> trouvera bien les commentaires du code
C. La signification des autres quantificateurs n'est pas changée.
</para>
<para>
Attention à ne pas confondre l'utilisation du point d'interrogation
ici avec son utilisation comme quantificateur lui-même.
A cause cette ambiguité, il peut apparaître des situations
où il faut le doubler : <literal>\d??\d</literal>. Ce masque va
tenter de lire un seul chiffre, mais le cas échéant,
il acceptera 2 chiffres pour permettre à la recherche
d'aboutir. Si l'option <link linkend="pcre.pattern.modifiers">PCRE_UNGREEDY</link>
est activée, (une option qui
n'est pas disponible avec Perl) alors les quantificateurs sont
non gourmand par défaut, mais peuvent être
rendu gourmand au cas par cas, en ajoutant un point d'interrogation
après. En d'autres termes, cette option inverse le comportement par
défaut.
</para>
<para>
Lorsqu'un sous-masque est quantifié avec un nombre minimum
de répétitions, qui soit plus grand que 1, ou avec
un maximum de répétitions, le masque compilé aura
besoin de plus de place de stockage, proportionnellement au minimum
et au maximum.
</para>
<para>
Si un masque commence par <literal>..*</literal> ou <literal>.{0,}</literal>
et que l'option <link linkend="pcre.pattern.modifiers">PCRE_DOTALL</link>
(équivalent en Perl à /s) est
activée, c'est-à-dire en autorisant le remplacement des nouvelles
lignes par un méta-caractère, alors le masque est
implicitement ancré, car tout ce qui suit va être
mangé par la première séquence, et se comportera
comme si le masque se terminait par le méta caractère
<literal>\A</literal>. Dans le cas où on sait d'avance qu'il
n'y aura pas de caractère de nouvelle ligne, activer l'option
<link linkend="pcre.pattern.modifiers">PCRE_DOTALL</link> et commencer
le masque par <literal>.*</literal> permet d'optmiser le masque.
</para>
<para>
Alternativement, on peut utiliser <literal>^</literal> pour ancrer
explicitement le masque. Lorsqu'un sous-masque capturant est
répété, la valeur capturée est la
dernière. Par exemple, après que
"<literal>(inter[net]{3}\s*)+</literal>" ai été
appliqué à "<literal>internet interne</literal>",
la valeur de la chaîne capturée est "<literal>interne</literal>".
</para>
<para>
Cependant, s'il y a des sous-masques imbriqués, la valeur
capturée correspondante peut l'avoir été lors
des précédentes itérations. Par exemple :
<literal>/(a|(b))+/</literal> accepte "<literal>aba</literal>" et
la deuxième valeur capturée est "<literal>b</literal>".
</para>
</refsect2>
<refsect2 id="regexp.reference.back_references">
<title>Références arrières </title>
<para>
En dehors des classes de caractères, un antislash suivi
d'un nombre plus grand que 0 (et possiblement plusieurs chiffres)
est une référence arrière (c'est à
dire vers la gauche) dans le masque, en supposant qu'il y ait
suffisamment de sous-masques capturants précédants.
</para>
<para>
Cependant, si le nombre décimal suivant l'antislash est
plus petit que 10, il sera toujours considéré
comme une référence arrière, et cela
génèrera une erreur si le nombre de capture
n'est pas suffisant. En d'autres termes, il faut qu'il existe
suffisamment de parenthèses ouvrantes à gauche
de la référence, surtout si la référence
est inférieure à 10.
</para>
<para>
Reportez-vous à la section "antislash" pour avoir de
plus amples détails à propos du nombre de
chiffres qui suivent l'antislash.
</para>
<para>
La référence arrière remplace ce qui a
été capturé par un sous-masque dans le
masque courant, plutôt que remplace le sous-masque
lui-même. Ainsi <literal>(calme|rapide)</literal> et
<literal>\1ment</literal> trouvera "<literal>calme et calmement</literal>"
et "<literal>rapide et rapidement</literal>", mais pas
"<literal>calme et rapidement</literal>". Si la recherche tient
compte de la casse, alors la casse de la chaîne
capturée sera importante. Par exemple,
<literal>((?i)rah)\s+\1</literal> trouve "<literal>rah rah</literal>"
et "<literal>RAH RAH</literal>", mais pas "<literal>RAH rah</literal>",
même si le sous-masque capturant initial ne tenait pas compte
de la casse.
</para>
<para>
Il peut y avoir plusieurs références arrières dans
le même sous-masque. Si un sous-masque n'a pas été
utilisé dans une recherche, alors les références
arrières échoueront. Par exemple "<literal>(a|(bc))\2</literal>"
ne réussira jamais si la chaîne sujet commence par
"<literal>a</literal>" plutôt que par "<literal>bc</literal>".
</para>
<para>
Etant donné qu'il peyt y avoir jusqu'à 99 références
arrières, tous les chiffres après l'antislash sont
considérés comment faisant potentiellement partie de
la référence arrière. Si le masque recherche un
chiffre après la référence, alors il faut
impérativement utiliser des délimiteurs pour terminer
la référence arrière.
</para>
<para>>
Si l'option <link linkend="pcre.pattern.modifiers">PCRE_EXTENDED</link>
est activée, on peut utiliser un espace.
Sinon, un commentaire vide fait l'affaire. Une référence
arrière qui intervient à l'intérieur de
parenthèses auquel elle fait référence
échouera dès que le sous-masque sera utilisé. Par exemple,
<literal>(a\1)</literal> échouera toujours. Cependant, ces
références peuvent être utiles dans les
sous-masques répétitifs. Par exemple, le masque
"<literal>(a|b\1)+</literal>" pourra convenir pour "<literal>a</literal>",
"<literal>aba</literal>", "<literal>ababaa</literal>", etc....
</para>
<para>
A chaque itération du sous-masque, la référence
arrière utilise le résultat du dernier sous-masque.
Pour que cela fonctionne, il faut que la première
itération n'ai pas besoin d'utiliser la référence
arrière. Cela arrive avec les alternatives, comme dans
l'exemple ci-dessus, ou avec un quantificateur de minimum 0.
</para>
</refsect2>
<refsect2 id="regexp.reference.assertions">
<title>Assertions</title>
<para>
Une assertion est un test sur les caractères suivants ou
précédent celui qui est en cours d'étude. Ce
test ne consomme par de caractère (ie, on ne déplace
pas le pointeur de caractères). Les assertions simples sont
codées avec <literal>\b</literal>, <literal>\B</literal>,
<literal>\A</literal>, <literal>\Z</literal>, <literal>\z</literal>,
<literal>^</literal> et <literal>$</literal>, et sont décrites
précédemment.
</para>
<para>
Il existe cependant un type d'assertions plus complexes, codées
sous la forme de sous-masques. Il en existe deux types : celles qui
travaillent au-delà de la position courante (<literal>\w+(?=;)</literal>),
et celles qui travaillent en deça (<literal>(?!)\w+</literal>).
</para>
<para>
Une assertion se comporte comme un sous-masque, hormis le fait qu'elle
ne déplace pas le pointeur de position. Les assertions avant
commencent par <literal>(?=</literal> pour les assertions positives, et
par <literal>(?!</literal>, pour les assertions négatives. Par exemple :
<literal>\w+(?=;)</literal> s'assure qu'un mot est suivi d'un point-virgule,
mais n'inclus pas le point virgule dans la capture. D'autre part,
<literal>(?!foo)bar</literal> en est proche, mais ne trouve pas une
occurrence de "<literal>bar</literal>" qui soit précédée
par quelque chose d'autre que "<literal>foo</literal>foo"; il trouve toutes
les occurrences de "<literal>bar</literal>", quelque soit ce qui
le précéde, car l'assertion <literal>(?!foo)</literal>
est toujours vraie quand les trois caractères suivants sont
"<literal>bar</literal>". Une assertion arrière est ici
nécessaire.
</para>
<para>
Les assertions arrières commencent par <literal>(?<=</literal>
pour les assertions positives, et <literal>(?<!</literal> pour les
assertions négatives. Par exemple : <literal>(?<!foo)bar</literal>
trouve les occurrences de "<literal>bar</literal>" qui ne sont pas
précédées par "<literal>foo</literal>".
</para>
<para>
Le contenu d'une référence arrière est limité
de telle façon que les chaînes qu'il utilise
soient toujours de la même taille. Cependant, lorsqu'il
y a plusieurs alternatives, elles n'ont pas besoin d'être
de la même taille. Par exemple, <literal>(?<=bullock|donkey)</literal>
est autorisé, tandis que <literal>(?<!dogs?|cats?)</literal>
provoque une erreur de compilation. Les alternatives qui ont des
longueurs différentes ne sont autorisées qu'au niveau
supérieur des assertions arrières. C'est une
amélioration du fonctionnement de Perl 5.005, qui impose
aux alternatives d'avoir toutes la même taille. Une
assertion telle que <literal>(?<=ab(c|de))</literal> n'est pas
autorisée, car l'assertion de bas niveau (la deuxième,
ici) a deux alternatives de longueurs différentes. Pour
la rendre acceptable, il faut écrire <literal>(?<=abc|abde)</literal>
</para>
<para>
L'implémentation des assertions arrières déplace
temporairement le pointeur de position vers l'arrière, et cherche
à vérifier l'assertion. Si le nombre de caractères
est différent, la position ne sera pas correcte, et l'assertion
échouera. La combinaison d'assertions arrières avec des
sous-masques peut être particulièrement pratique à
fin des chaînes. Un exemple est donné à la fin de
cette section.
</para>
<para>
Plusieurs assertions peuvent intervenir successivement. Par exemple,
le masque <literal>(?<=\d{3})(?<!999)foo</literal> recherche
les chaînes "<literal>foo</literal>" précédées
par trois chiffres qui ne sont pas "999". Notez que chaque assertion
est appliquées indépendemment, au même point de
la chaîne à traiter. Tout d'abord, il est
vérifié que les trois premiers caractères ont
tous des chiffres, puis on s'assure que ces trois caractères
ne sont pas "<literal>999</literal>". Le masque précédant
n'accepte pas "<literal>foo</literal>" précédé de
6 caractères, les trois premiers étant des chiffres et
les trois suivants étant différents de "<literal>999</literal>".
Par exemple, ce masque n'acceptera pas la chaîne
"<literal>123abcfoo</literal>". Pour ce faire, il faut utiliser le masque
suivant : <literal>(?<=\d{3}...)(?<!999)foo</literal>. Dans ce
masque, la première assertion vérifie les six premiers
caractères, s'assure que les trois premiers sont des entiers,
et la deuxième assertion s'assure que les trois derniers
caractères ne sont pas "<literal>999</literal>".
</para>
<para>
De plus, les assertions peuvent être imbriquées :
<literal>(?<=(?<!foo)bar)baz</literal> recherche les
occurrences de "<literal>baz</literal>" qui sont
précédées par "<literal>bar</literal>", qui,
à son tour, n'est pas précédé par
"<literal>foo</literal>". Au contraire,
<literal>(?<=\d{3}(?!999)...)foo</literal> est un autre masque,
qui recherche les caractères "<literal>foo</literal>",
précédés par trois chiffres, suivis trois
autres caractères qui ne forment pas "<literal>999</literal>".
Les assertions ne sont pas capturantes, et ne peuvent pas être
répétées. Si une assertion contient des sous-masques
capturants en son sein, ils seront compris dans le nombre de sous-masques
capturants du masque entier. La capture est réalisée pour
les assertions positives, mais cela n'a pas de sens pour les
assertions négatives.
</para>
<para>
200 assertions au maximum sont autorisées.
</para>
</refsect2>
<refsect2 id="regexp.reference.onlyonce">
<title>Sous-masques uniques</title>
<para>
Avec les quantificateurs de répétitions, l'échec
d'une recherche conduit normalement à une autre recherche, avec
un nombre différent de répétitions, pour
voir si le masque ne s'applique pas dans d'autres conditions.
Parfois, il est pratique d'éviter ce comportement, soit
pour changer la nature de la recherche, soit pour la faire abandonner
plus tôt, si on pense qu'il n'est pas besoin d'aller plus loin.
</para>
<para>
Considérons par exemple, le masque <literal>\d+foo</literal>
appliqué à la ligne <literal>123456bar</literal>.
Après avoir tenté d'utiliser les 6 chiffres suivi
de "<literal>foo</literal>" qui font échouer, l'action habituelle
sera de réessayer avec 5 chiffres, puis avec 4, et ainsi de
suite jusqu'à l'échec final.
</para>
<para>
Un sous-masque évalué une seule fois permettrait
d'indiquer que lorsqu'une partie du masque est trouvée, elle
n'a pas besoin d'être réévaluée à
chaque tentative. Ceci conduirait à ce que la recherche
échoue immédiatement après le premier test.
Ces assertions ont leur propre notation, commençant avec
<literal>(?></literal> comme ceci : <literal>(?>\d+)bar</literal>.
</para>
<para>
Ce type de parenthèses verrouille le sous-masque qu'il contient
un fois qu'il a été trouvé, et empêche un
échec ultérieur d'y repasser, mais autorise à
revenir plus loin en arrière. Une autre description est que
les sous-masques de ce type recherche les chaînes de
caractères, et les ancre le sous-masque à l'intérieur
de la chaîne.
</para>
<para>
Les sous-masques uniques ne sont pas capturants. Des cas simples comme
ceux présentés ci-dessus peuvent être pris comme
des situations maximisantes, qui réservent le maximum de
caractères. En effet, alors que <literal>\d+</literal> et
<literal>\d+?</literal> ajustent le nombre de chiffres trouvés
de manière à laisser la possibilité au masque de
réussir, <literal>(?>\d+)</literal> ne peut retenir que la
séquence entière de chiffres. Cette construction peut
contenir un nombre arbitraire de sous-masques complexes, et ils peuvent
être imbriqués.
</para>
<para>
Les sous-masques uniques ne peuvent être utilisés qu'avec
les assertions arrières, pour effectuer une recherche efficace
en fin de chaîne. Considérons un masque simple tel que
"<literal>abcd$</literal>" appliqué à une très
longue chaîne qui ne lui correspond pas. A cause du système
de recherche de gauche à droite, PCRE va commencer par rechercher
un "<literal>a</literal>" dans la chaîne sujet, puis vérifier
si ce qui suit convient au reste du masque. Si le masque est
spécifié sous la forme <literal>^.*abcd$</literal>
alors, la séquence <literal>.*</literal> remplace en premier
lieu la chaîne entière, et échoue, repart en
arrière, et remplace tous les caractères sauf le dernier,
échoue, retourne en arrière, prend un caractère
de moins, etc... et ainsi de suite. Encore une fois, la recherche du
"<literal>a</literal>" passe en revue toute la chaîne de gauche
à droite, ce qui n'est pas très efficace. Par contre,
si le masque était écrit <literal>^(?>.*)(?<=abcd)</literal>
alors il n'y aurait pas de retour en arrière, pour satisfaire
la séquence <literal>.*</literal>, car elle ne peut que remplacer
toute la chaîne. L'assertion arrière consécutive
va alors faire un test sur les 4 derniers caractères. Si elle
échoue, la recherche est immédiatement interrompue.
</para>
<para>
Pour les chaînes très longues, cette approche fait la
différence en terme de performances et de temps de recherche.
Lorsqu'un masque contient une répétition illimitée
dans un sous-masque, qui contient lui-même un nombre
illimité de répétiteur, l'utilisation des
sous-masques à utilisation unique sont la seule façon
d'éviter l'échec de la recherche à après un
temps de calcul trop long.
</para>
<para>
Le masque <literal>(\D+|<\d+>)*[!?]</literal> recherche un nombre
illimité de sous-chaînes, qui contiennent soit
des non-chiffres, soit des chiffres inclus dans <>, suivi soit
par <literal>!</literal> ou par <literal>?</literal>. Lorsqu'il trouve
une solution, ce masque va très vite. Mais, lorsqu'il est
appliqué à une chaîne telle que :
<literal>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</literal>,
il lui faut beaucoup de temps pour annoncer un échec. Cela est
dû au fait que la chaine peut être divisée en deux
sous-chaînes d'un grand nombre de façons, et qu'elles
ont toutes été essayées. (Cet exemple utilisait
<literal>[!?]</literal> plutôt qu'un caractère simple, car
PCRE et PHP utilise une optimisation qui leur permettent de détecter
rapidement l'échec lorsqu'un caractère unique est
trouvé. Il se souvient du dernier caractère qui est
attendu, et s'aperçoit rapidement qu'il n'y a pas ce caractère).
</para>
<para>
Si le masque utilisé est <literal>((?>\D+)|<\d+>)*[!?]</literal>
les séquences de chiffres ne peuvent pas être
trouvées, et l'échec intervient rapidement.
</para>
</refsect2>
<refsect2 id="regexp.reference.conditional">
<title>Les sous-masques conditionnels</title>
<para>
Il est possible de lier un sous-masque à une condition, ou de
choisir entre deux sous-masques alternatifs, en fonction du
résultat d'une assertion, ou suivant les résultats
de recherche précédents.
</para>
<para>
Les deux formes possibles de sous-masques conditionnels sont
<literal>(?(condition)masque positif)</literal> et
<literal>(?(condition) masque positif | masque négatif)</literal>.
</para>
<para>
Si les conditions sont satisfaites, le masque positif est utilisé,
sinon, le masque négatif est utilisé, si présent.
S'il y a plus de deux alternatives, une erreur est générée
à la compilation.
</para>
<para>
Il y a deux types de conditions : si le texte entre les parenthèses
est une séquence de chiffres, alors la condition est satisfaite si
le sous-masque correspondant à ce numéro a réussi.
Considérons le masque suivant, qui contient des espaces non
significatifs pour le rendre plus compréhensible (on supposera
l'option <link linkend="pcre.pattern.modifiers">PCRE_EXTENDED</link>
activée) et qui est divisé en trois parties
pour simplifier les explications : <literal>( \( )? [^()]+ (?(1) \) )</literal>.
</para>
<para>
La première partie recherche une parenthèse ouvrante
optionnelle, et si elle existe, elle est capturée. La deuxième
partie recherche un séquence de caractères qui ne contiennent
pas de parenthèses. La troisième partie est
conditionnée à la première, et s'assure que s'il
y avait une parenthèse ouvrante, il en existe une fermante.
Si une parenthèse ouvrante a été trouvée,
elle a été capturée, et donc la première capture
existe, et la condition est exécutée. Sinon, elle est
ignorée.
</para>
<para>
Ce masque recherche donc une séquence de lettres, éventuellement
placées entre parenthèse. Si la condition n'est pas une
séquence de chiffres, il faut que ce soit une assertion.
Ce peut être une assertion positive ou négative,
arrière ou avant. Considérons le masque suivant
(même conditions que le précédent) et avec deux
alternatives en seconde ligne :
<literal>(?(?=[^a-z]*[a-z])\d{2}[a-z]{3}-\d{2} | \d{2}-\d{2}-\d{2} )</literal>.
La condition est une assertion avant positive, qui recherche une
séquence optionnelle de caractères non-lettre. En d'autres
termes, elle teste la presence d'au moins une lettre dans la chaîne
sujet. Si une lettre est trouvée, la recherche se poursuit avec
la première alternative, et sinon, avec la seconde. Ce masque
recherche des chaînes de la forme <literal>dd-aaa-dd</literal> ou
<literal>dd-dd-dd</literal>, avec "<literal>aaa</literal>" qui sont des
lettres, et <literal>dd</literal> qui sont des chiffres.
</para>
</refsect2>
<refsect2 id="regexp.reference.comments">
<title>Commentaires</title>
<simpara>
La séquence <literal>(?#</literal> marque le début d'un commentaire,
qui se termine à la prochaine parenthèse fermante. Les
parenthèses imbriquées ne sont pas autorisées. Les
caractères entre ces délimiteurs ne jouent alors aucun rôle
dans le masque.
</simpara>
<simpara>
Si l'option <link linkend="pcre.pattern.modifiers">PCRE_EXTENDED</link>
est activée, les caractères dièses
<literal>#</literal> non échappés en dehors d'une classe de
caractères introduisent un commentaire qui continuera jusqu'à
la prochaine ligne dans le masque.
</simpara>
</refsect2>
<refsect2 id="regexp.reference.recursive">
<title>Masques récursifs</title>
<para>
Considérons le cas où il faut recherche dans une
chaîne, avec un niveau d'imbrications infini de
parenthèses. Sans l'aide de la récursivité, le
mieux que nous puissions obtenir est de créer un masque avec un
niveau fixé de profondeur d'imbrication. Il n'est pas possible
de traiter des masques à niveau d'imbrications variable.
PCRE fournit un nouvel outil expérimental qui permet
d'utiliser la récursivité dans les masques (entre autre).
L'option <literal>(?R)</literal> est fournie pour servir la cause de
la récursivité. Le masque suivant résoud le
problème des parenthèses (l'option
<link linkend="pcre.pattern.modifiers">PCRE_EXTENDED</link> est
utilisée pour ignorer les espaces) :
<literal>\( ( (?>[^()]+) | (?R) )* \)</literal>
</para>
<para>
Tout d'abord, le masque recherche une parenthèse ouvrante. Puis,
il recherche n'importe quel nombre de sous-chaînes qui sont soit
des séquences de caractères non-parenthèses, ou
bien une recherche récursive avec le même masque (i.e.
une chaîne correctement incluse entre parenthèses).
Finalement, il recherche une parenthèse fermante.
</para>
<para>
Cet exemple particulier contient un nombre illimité de
répétitions imbriquées, ce qui fait que
l'utilisation de sous-chaînes à utilisation unique
pour rechercher les séquence de caractères
non-parenthèses est important, lorsqu'il s'applique à
une chaîne qui n'est pas valide. Par exemple, si on l'applique
à "<literal>(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa()</literal>"
la réponse arrive rapidement. Sinon, si les sous-chaînes
à utilisation unique ne sont pas utilisées, la
recherche peut prendre un très long temps, car il existe
de très nombreuses combinaisons de <literal>+</literal> et
<literal>*</literal> à tester avant de conclure à
l'échec.
</para>
<para>
Les valeurs utilisées pour capturer les sous-masques sont celles
utilisées par les niveaux les plus hauts de
récursivités, auquel la valeur est fixée.
Si le masque précédent est utilisé avec
<literal>(ab(cd)ef)</literal> la valeur de la parenthèse
capturante est "<literal>ef</literal>", qui est la dernière
valeur lue au niveau supérieur. Si de nouvelles
parenthèses sont ajoutées, par exemple :
<literal>\( ( ( (?>[^()]+) | (?R) )* ) \)</literal>
alors la chaîne capturée est "<literal>ab(cd)ef</literal>",
c'est-à-dire le contenu de la parenthèses capturant
de plus haut niveau. S'il y a plus de 15 parenthèses
capturantes dans une chaîne, PCRE doit utiliser plus
de mémoire pour stocker ces données. S'il ne
peut obtenir cette mémoire supplémentaire, il ne fait
que sauver les 15 premières, car il n'y a pas moyen de
générer une erreur de mémoire lors d'une
récursion.
</para>
</refsect2>
<refsect2 id="regexp.reference.performances">
<title>Performances</title>
<para>
Certaines séquences de recherches sont plus efficaces que d'autres.
Ainsi, il est plus efficace d'utiliser une classe de caractères
telle que <literal>[aeiou]</literal> plutôt qu'une alternative
<literal>(a|e|i|o|u)</literal>.
</para>
<para>
En général, le masque le plus simple, qui permette
la recherche désirée est le plus efficace. Le livre
de Jeffrey Friedl's contient de nombreuses études à
propos de l'optimisation des expressions régulières.
</para>
<para>
Lorsqu'un masque commence par.* et que l'option
<link linkend="pcre.pattern.modifiers">PCRE_DOTALL</link> est
activée, le masque est implicitement ancré par PCRE,
étant donné qu'il ne peut que rechercher au début
de la chaîne. Cependant, si option
<link linkend="pcre.pattern.modifiers">PCRE_DOTALL</link> n'est pas
activée, PCRE ne peut faire aucune optimisation car le
méta-caractères point "<literal>.</literal>"
ne remplace pas une nouvelle ligne, et si la chaîne
sujet contient des nouvelles lignes, le masque peut trouver une
solution qui serait située juste après une
de ces nouvelles lignes, et non pas seulement au début
de la chaîne sujet. Par exemple, le masque,
<literal>(.*)second</literal> acceptera la chaîne
"<literal>premier \net second</literal>" (avec "<literal>\n</literal>"
qui remplace la nouvelle ligne), et la première chaîne
capturée sera "<literal>et</literal>".
</para>
<para>
Afin d'effectuer la recherche, PCRE va essayer d'appliquer le masque
à partir de chaque début de ligne. Si vous utilisez un
tel masque avec des chaînes qui ne contiennent pas de
caractères de nouvelles lignes, les meilleures performances
seront atteintes avec l'option
<link linkend="pcre.pattern.modifiers">PCRE_DOTALL</link>, ou en ancrant le
masque avec <literal>^.*</literal>. Cela évite à PCRE
de scanner toute la chaîne pour rechercher un caractère
de nouvelle ligne et recommencer la recherche.
</para>
<para>
Attention aux masques qui contiennent des quantificateurs infinis
imbriqués. Ils peuvent demander un temps de calcul très
long, lorsqu'appliqués à une chaîne qui ne
correspond pas à ce masque. Par exemple, <literal>(a+)*</literal>
peut accepter "<literal>aaaa</literal>" de 33 manières
différentes, et ce nombre croit rapidement avec la taille
de la chaîne (le quantificateur <literal>*</literal> peut prendre
les valeurs de 0, 1, 2, 3, ou 4, et pour chaque cas non nul, le
quantificateur <literal>+</literal> peut prendre différentes
valeurs).
</para>
<para>
Lorsque le reste de la chaîne est tel que l'on s'achemine
vers un échec, PCRE doit en principe vérifier
toutes les possibilités, et cela prend un temps
extrêmement long. Un optmiseur repère les cas
les plus simples, tel que <literal>(a+)*b</literal> où
un caractère simple suit les quantificateurs. Avant de partir
dans les procédures standard de recherche, PCRE
s'assure qu'il y a au moins un "<literal>b</literal>" dans la
chaîne, et si ce n'est pas le cas, l'échec est
annoncé immédiatement. Sinon, il n'y a pas
d'optimisation dans la recherche. Vous pouvez voir la
différence de comportement avec le masque suivant :
<literal>(a+)*\d</literal>. Le premier retourne un échec
quasi-immédiatement, s'il est appliqué à
une ligne de "<literal>a</literal>", alors que le second masque
prend un temps significatif pour une chaîne de plus de
20 caractères.
</para>
</refsect2>
</refsect1>
</refentry>
</reference>
<!-- Keep this comment at the end of the file
Local variables:
mode: sgml
sgml-omittag:t
sgml-shorttag:t
sgml-minimize-attributes:nil
sgml-always-quote-attributes:t
sgml-indent-step:1
sgml-indent-data:t
indent-tabs-mode:nil
sgml-parent-document:nil
sgml-default-dtd-file:"../../manual.ced"
sgml-exposed-tags:nil
sgml-local-catalogs:nil
sgml-local-ecat-files:nil
End:
-->
|