IMPORTANT: Per accedir als fitxer de subversion: http://acacha.org/svn (sense password). Poc a poc s'aniran migrant els enllaços. Encara però funciona el subversion de la farga però no se sap fins quan... (usuari: prova i la paraula de pas 123456)

Linux Professional Institute Certificate. LPIC-1

Lpic1 large.gif
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.

Objectius del tema

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
Objective.jpg
  • Objectiu: Els candidats han de ser capaços de manipular fitxers i dades de text utilitzant expressions regulars. Aquest objectiu inclou la creació d'expressions regulars simples que continguin diversos elements de notació. També inclou l'ús d'eines d'expressions regulars per a fer cerques al sistema de fitxers o en els continguts d'un fitxer.
  • Pes: 2
060317 Icon - Theory of Knowledge v01 pdc.jpg

Àrees Clau de Coneixement:

Icon list.jpg

La següent és una llista parcial de fitxers, termes i utilitats utilitzades:

Text-editor.svg

Apunts: LPI 103.7. Fer cerques en fitxers de text utilitzant expressions regulars

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.

Conceptes

  • Interpret d'expressions regulars: Programa o aplicació capaç d'interpretar expressions regulars.
  • Coincidència (match): Els intèrprets d'expressions regulars busquen coincidències en un text. Aquest coincidències són anomenades matchs
  • Patrons (patterns): Les expressions regulars permeten especificar patrons de text. Els patros poden ser simples com una paraula o un caràcter o complexos. Els patrons complexos s'expressen mitjançant caràcters especials
  • branques (branches): Els patrons s'expressen com una o més branques no buides separades per | (operador OR). És a dir coincideix amb qualsevol text que coincideixi amb qualsevol de les branques
  • Peces (pieces): Una branca està formada per una o més peces concatenades (les concatenacions s'expressen sense cap caràcter especial: abc és la concatenació de a més b més c). Una peça és un àtom seguit de un sol caràcter '*', '+', '?' o un bound (els quantificadors).
  • àtom (atom): Són expressions regulars tancades entre parèntesis "()". "()" és equivalent a l'string null. Consulteu Parèntesi
  • bound: s'expressen utilitzant els caràcters '{' i '}'. Consulteu Operadors de repetició. Quantificadors i bounds
  • Classes: es posen entre parèntesis quadrats (square brackets) "[]". Consulteu Expressions regulars amb claudàtors

Vegeu:

$ man 7 regex

Sintaxi de les expressions regulars

Segons el manual i l'estàndard POSIX:

$ man 7 regex

Hi ha dos tipus d'expressions regulars:

  • Bàsiques: Els caràcters ?,+ i | i els símbols ( i ) perden el seu significat especial i compten com a caràcters normals i corrents. Alguns programes que suporten expressions regulars bàsiques, permeten que aquests símbols tinguin el seu significat especial si s'escapen amb el caràcter barra invertida (\), per exemple \?. Algunes ordres com ed utilitzant aquest format.
  • Extenses: Els exemples i explicacions d'aquesta wiki són per a expressions extenses. Les diferències són subtils entre els dos tipus d'expressions però els fonaments són les mateixos.

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.

Seqüències de caràcters

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'

Expressions amb claudàtors ([]). Classes

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!).

Expressions amb rang [valorinicial-valorfinal]

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

Qualsevol caràcter simple (.)

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.

Operadors de repetició. Quantificadors i bounds

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:

  • ? o + *: caràcters especials de quantificació
  • Bounds: S'utilitzen com a quantificadors que permeten indicar rangs exactes de quantificació. S'utilitzen els caràcters { i }

Exemples

  • Part opcional ?:
ab? equival a les frases a, ab
  • Part repetible (una o més) +:
ab+ equival a ab, abb, abbb, abbbb, ...
  • Part repetible opcional (zero o més) *:
ab* equival a a, ab, abb, abbb, ...

Exemples amb quantificadors

  • Part repetible {mínim, màxim}:
ab{2,3} equival a abb i abbb
  • Part repetible {nombre exacte}:
ab{2} equival a abb
  • Part repetible tant o més {mínim,}
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" '{'

Expressió regular per a indicar qualsevol coincidència (.*)

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

Múltiples conjunts de caràcters (|)

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

Parèntesi

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, ...

Inici i final de línia (^ i $). Àncores

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.

Escapar caràcters especials

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 '\'.

Seqüències d'escapament

\n 
Salt de línia
\t 
Tabulador horitzontal
\r 
Salt de carro
\f 
Salt de pàgina
\v 
Tabulador vertical
\s 
espaiat: [ \n\t\r\f\v]

Expressions Posix

símbols multi-caràcter en una classe [. .]
[a-c[.ch.]d-z] := inclou la ch castellana en una classe alfabet
classe de caràcters equivalents en la ordenació local [= =]
d [ [=e=] ] u és el mateix que d[eéè]u
[:digit:]
[0-9]
[:alnum:]
caràcters alfanumèrics segons localització (LOCALE) actual
[:alpha:]
caràcters alfabètics segons localització (LOCALE) actual
[:blank:]
espai, tabulador
[:xdigit:]
[0-9A-Fa-f]
[:punct:]
Símbols de puntuació . , " ' ? ! ; :
[:print:]
Qualsevol caràcter imprimible
[:space:]
[ \t\r\n\v\f].
[:graph:]
caràcters gràfics (visibles): exclou [:space:].
[:upper:]
majúscules segons localització (LOCALE) actual
[:lower:]
minúscules segons localització (LOCALE) actual
[:cntrl:]
Caràcters de control

Referències enrere (back references)

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.

Voracitat: minimitzar repeticions

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.

Exemples

Processar un fitxer XML

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 /.

Expressions regulars bàsiques

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 '^').

Documentació

regex(7)

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

Comandes

grep

Consulteu grep.

egrep

Consulteu egrep.

fgrep

Consulteu fgrep.

rgrep

Consulteu rgrep.

sed

Consulteu sed.

Resol·lució de problemes

Mínuscules i majúscules

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.


Mida màxima de les expressions regulars

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.

Vegeu també

Enllaços externs