Certificat | LPIC-1 |
Examen: | 101 (torneu a la resta de temes) |
Fitxers: | LPI_103.7.FerCerquesFitxersTextUtilitzantExpressionsRegulars.pdf (LPI_103.7.FerCerquesFitxersTextUtilitzantExpressionsRegulars.odp) |
Objectius: | http://www.lpi.org/eng/certification/the_lpic_program/lpic_1/exam_101_detailed_objectives |
Dipòsit SVN: | https://svn.projectes.lafarga.cat/svn/lpi/Materials/Examen_101/103.7 |
Usuari: | anonymous |
Paraula de pas: | qualsevol paraula de pas |
En informàtica, les expressions regulars (aka RE's) són utilitzades per multitud d'aplicacions, llenguatges de programació, ordres, etc. La seva funció és expressar patrons de text. Una expressió regular pot ser tant simple com un text normal i corrent (el patró és exactament el text escrit) o podem complicar-les mitjançant caràcters especials que ens permeten expressar patrons més complexes.
La funcionalitat de les expressions regulars és similar a la dels comodins (wildcards). La potència (i complexitat) de les expressions regulars permet expressar patrons de text molt més complexes.
IMPORTANT: La sintaxi de les expressions regulars no és igual per a tots els llenguatges programació, havent-hi particularitats segons l'idioma (Perl, PHP, Java... Per a l'examen 101 és tenen en compte les anomenades expressions regulars unix. Consulteu w:Expressions regulars per tal de tenir més informació sobre les particularitats de les expressions regulars per a cada llenguatge de programació. )
103.7. Fer cerques en fitxers de text utilitzant expressions regulars | |
---|---|
![]() |
|
![]() |
Àrees Clau de Coneixement:
|
![]() |
La següent és una llista parcial de fitxers, termes i utilitats utilitzades: |
![]() |
Apunts: LPI 103.7. Fer cerques en fitxers de text utilitzant expressions regulars |
En informàtica, una expressió regular (o col·loquialment anomenades regexp, acrònim de l'anglès regular expression) és una representació, segons unes regles sintàctiques d'un llenguatge formal, d'una porció de text genèric a buscar dins d'un altre text, com per exemple uns caràcters, paraules o patrons de text concrets.
El text genèric de l'expressió regular pot representar patrons (en anglès patterns) amb determinats caràcters que tenen un significat especial (per exemple, en el cas del shell d'unix, el caràcter comodí "?" per representar un caràcter qualsevol, el caràcter comodí "*" per representar un nombre qualsevol de caràcters, o classes com "[abc]" per representar qualsevol dels caràcters 'a', 'b' o 'c').
Una expressió regular està escrita seguint les regles d'un llenguatge formal, que poden ser interpretades per un programa processador d'expressions regulars, capaç d'examinar un text i reconèixer-hi les parts que es corresponen (en anglès match) amb l'expressió regular especificada.
Molts processadors de textos i llenguatges de programació fan ús de les seves pròpies expressions regulars per a procediments de cerca o bé de cerca i substitució de textos.
Vegeu:
$ man 7 regex
Segons el manual i l'estàndard POSIX:
$ man 7 regex
Hi ha dos tipus d'expressions regulars:
Cal tenir en compte que POSIX.2 deixa oberts certs aspectes semàntics oberts a la interpretació. Això provoca que cada llenguatge hagi pres decisions diferents sobre la interpretació de les expressions regulars.
NOTA: En aquest article es parlarà principalment de les expressions regulars Unix. Al manual (man 7 regex), les decisions pròpies de Unix s'indiquen amb un ! entre parèntesis.
El tipus d'expressió regular ha utilitzar depèn del programa, trobarem programes que només accepten un dels dos tipus i altres que accepten tots dos.
NOTA: També és possible que trobeu programes que utilitzen una variant pròpia (similar però amb certs matisos) de les expressions regulars estàndard.
L'expressió regular més simple conté el text amb el que volem treballar. Per exemple
Ethernet
Aquesta expressió regular coincidirà amb qualsevol text que contingui els caràcters Ethernet.
La potència de les expressions regulars la trobem en l'ús de caràcters especials. Vegem algunes del més importants en els següents apartats.
Són les expressions regulars més senzilles ja que permeten expressar una simple juxtaposició de caràcters. Per exemple:
ab equival a 'a' seguit de 'b'
Els caràcters que estiguin entre claudàtors (també anomenats parèntesis rectangulars), constitueixen expressions regulars que coincideixen amb qualsevol del caràcter de l'interior dels claudàtors.
Per exemple, la expressió regular:
p[aeiou]t
Coincidirà amb els següents texts:
pat pet pit pot put
Acabem doncs de veure una forma de expressar el patró: una vocal minúscula (sense accents!).
Són una variant de les expressions entre corxetes. En aquest cas però s'expressen rangs de caràcters. Els rangs s'expressen de la següent forma:
valorinicial-valorfinal
Per exemple:
[2-6]x
Coincideix amb els texts:
2x 3x 4x 5x 6x
El punt (.) representa qualsevol caràcter excepte el caràcter de salt de línia. Per exemple l'expressió:
p.t
Concorda amb qualsevol text que tingui qualsevol caràcter (però només un) entre la p i la t:
pat pet pwt p?t ...
En anglès el punt és anomenat dot.
Permeten indicar quants cops haurà de coincidir un patró. Segons els manual:
$ man 7 regex ... A piece is an atom possibly followed by a single(!) '*', '+', '?', or bound. An atom followed by '*' matches a sequence of 0 or more matches of the atom. An atom followed by '+' matches a sequence of 1 or more matches of the atom. An atom followed by '?' matches a sequence of 0 or 1 matches of the atom. A bound is '{' followed by an unsigned decimal integer, possibly followed by ',' possibly followed by another unsigned decimal integer, always followed by '}'. The integers must lie between 0 and RE_DUP_MAX (255(!)) inclusive, and if there are two of them, the first may not exceed the second. An atom followed by a bound containing one integer i and no comma matches a sequence of exactly i matches of the atom. An atom followed by a bound containing one integer i and a comma matches a sequence of i or more matches of the atom. An atom followed by a bound containing two integers i and j matches a sequence of i through j (inclusive) matches of the atom.
Tingueu en compte la nomenclatura utilitzada: una peça (piece) és un àtom més un quantificador
Hi ha dos tipus:
Exemples
ab? equival a les frases a, ab
ab+ equival a ab, abb, abbb, abbbb, ...
ab* equival a a, ab, abb, abbb, ...
Exemples amb quantificadors
ab{2,3} equival a abb i abbb
ab{2} equival a abb
ab{4} equival a abbb, abbbb, abbbbb ...
IMPORTANT: Un '{' seguit de qualsevol caràcter que no sigui un numèric és considerat com el caràcter "normal" '{'
Una de les expressions regulars més utilitzades és:
.*
Que especifica qualsevol conjunt de caràcters. Per exemple:
Un.*meravellós
Coincidirà amb qualsevol text on aparegui el text Un seguit de qualsevol text i l'adjectiu meravellós. Per exemple:
Un dia meravellós Un regal meravellós Un cotxer meravellós
O fins i tot:
Undiameravellós
Permet indicar múltiples opcions, és dir utilitzar l'operador OR:
a|b equival als caràcters 'a' o 'b'
Tingueu en compte que poden indicar també paraules completes:
gos|gat
o
cotxe|moto
Els parèntesis (()) serveixen per embolcallar subexpressions i s'utilitzen per indicar en quin ordre s'han d'interpretar les subexpressions d'expressions regulars complexes.
Per exemple, podem agrupar un conjunt de ORs (|) entre parèntesi:
(cotxe|moto|camió)
Sovint s'utilitzen conjuntament amb els quantificadors:
(ab)+ equival a ab, abab, ababab, abababab, ...
El caràcter ^ representa l'inici de línia.
El caràcter dol·lar ($) representa el final de la línia.
El caràcter ^ s'anomena carat en anglès i el caràcter dol·lar ($) s'anomena dollar.
Si volem crear una expressió regular que coincideixi amb alguns dels caràcters especials, aleshores hem d'escapar el caràcter amb una barra invertida (\). Per exemple, per tal de crear una expressió regular que coincideixi amb una adreça IP:
192\.168\.1\.1
coincidirà amb el text:
192.168.1.1
En anglès la barra invertida s'anomena backslash.
Segons el manual:
$ man 7 regex ... a '\' followed by one of the characters "^.[$()|*+?{\" (matching that character taken as an ordinary character), a '\' followed by any other character(!) (matching that character taken as an ordinary character, as if the '\' had not been present(!)), or a single character with no other significance (matching that character)
Els caràcters especials són:
^ . [ $ ( ) | * + ? { \
Tingueu en compte que si escapeu caràcters normals serà com si no haguessiu fet res, és a dir:
\a equival a a
NOTA: També podeu utilitzar l'ordre fgrep que permet fer cerques en text fixes, sense expressions regulars
IMPORTANT: És il·legal acabar una expressió regular amb '\'.
Hi ha un nou tipus d'atoms anomenat referència enrere (back reference):
'\' seguit d'un digit decimal diferent de zero
Exemple:
\([bc]\)\1
Coincideix amb "bb" o "cc" però no amb bc
NOTA: Segons el manual no es recomana utilitzar les Back references:
$ man 7 regex ... are a dreadful botch, posing major problems for efficient implementations. They are also somewhat vaguely defined (does "a\(\(b\)*\2\)*d" match "abbbd"?). Avoid using them.
El signe ? després dels quantificadors ? * + indica que el patró s'ha de satisfer amb el menor nombre de repeticions possible (mandrós en anglès lazy), en comptes del comportament habitual contrari (cobejós o voraç, en anglès greedy).
Per exemple, si es busca l'expressió regular "g.*os" al text "el gos busca un os", el comportament per defecte del processador és retornar la porció de text més llarga possible que es correspon amb l'expressió buscada, que en aquest cas el resultat seria "gos busca un os", amb el tipus de comportament que anomenem "voraç" o greedy.
En canvi buscant l'expressió regular "g.*?os" al mateix text, el processador retornarà la porció de text més curta possible que es correspon amb l'expressió buscada, i en aquest cas el resultat seria "gos", amb el tipus de comportament que anomenem "mandrós" o lazy.
En programes que permeten manipulació del text trobat (per exemple amb programes sed o awk, no pas grep, però sí egrep):
Referències als grups de text (entre parèntesis) excepte cas especial, segons ordre, \1 \2 .. \9
<([a-z][a-z0-9]*)[^>]*>([^<]*)</\1>
reconeix un etiquetat XML amb etiqueta de tancament igual a la d'inici, noteu \1 després de /.
TODO:
Obsolete ("basic") regular expressions differ in several respects. '|', '+', and '?' are ordinary characters and there is no equivalent for their functionality.
The delimiters for bounds are "\{" and "\}", with '{' and '}' by themselves ordinary characters. The parentheses for nested subexpressions are "\(" and "\)", with '(' and ')' by themselves ordinary characters. '^' is an ordinary character except at the beginning of the RE or(!) the beginning of a parenthesized subexpression, '$' is an ordinary character except at the end of the RE or(!) the end of a parenthesized subexpression, and '*' is an ordinary character if it appears at the beginning of the RE or the beginning of a parenthesized subexpression (after a possible leading '^').
Podeu utilitzar el manual de Linux per tal d'obtenir més informació sobre les expressions regulars:
IMPORTANT: Cal consultar la secció 7 del manual
$ man 7 regex REGEX(7) Linux Programmer’s Manual REGEX(7 ) NAME regex - POSIX.2 regular expressions DESCRIPTION Regular expressions ("RE"s), as defined in POSIX.2, come in two forms: modern REs (roughly those of egrep; POSIX.2 calls these "extended" REs) and obsolete REs (roughly those of ed(1); POSIX.2 "basic" REs). Obsolete REs mostly exist for backward compati‐ bility in some old programs; they will be discussed at the end. POSIX.2 leaves some aspects of RE syntax and semantics open; "(!)" marks decisions on these aspects that may not be fully portable to other POSIX.2 implementations. ...
El manual es proveït pel paquet manpages:
$ whereis regex regex: /usr/include/regex.h /usr/share/man/man7/regex.7.gz /usr/share/man/man3/regex.3.gz $ dpkg -S /usr/share/man/man7/regex.7.gz manpages: /usr/share/man/man7/regex.7.gz
Consulteu grep.
Consulteu egrep.
Consulteu fgrep.
Consulteu rgrep.
Consulteu sed.
TODO:
If case-independent matching is specified, the effect is much as if all case distinctions had vanished from the alphabet. When an alphabetic that exists in multiple cases appears as an ordinary character outside a bracket expression, it is effectively transformed into a bracket expression containing both cases, for example, 'x' becomes "[xX]". When it appears inside a bracket expression, all case counterparts of it are added to the bracket expression, so that, for example, "[x]" becomes "[xX]" and "[^x]" becomes "[^xX]".
POSIX.2's specification of case-independent matching is vague. The "one case implies all cases" definition given above is current consensus among implementors as to the right interpretation.
2 POSIX.2's specification of case-independent matching is vague. The "one case implies all cases" definition given above is current consensus among implementors as to
the right interpretation.
Segons el manual:
$ man 7 regex ... No particular limit is imposed on the length of REs(!). Programs intended to be portable should not employ REs longer than 256 bytes, as an implementation can refuse to accept such REs and remain POSIX-compliant.
No hi ha limit per a les expressions regulars a Unix. De totes formes es recomana que per tal de ser POSIX-compliant no es superin els 256 bytes.