Регулярен израз

от Уикипедия, свободната енциклопедия
Направо към: навигация, търсене

В информатиката регулярен израз (на английски: regular expression), или още стандартен израз (редовен/рутинен израз), е низ от знаци/символи, който описва множества или подмножества с помощта на определени синтактични правила.

Регулярни изрази в теоретичната информатика[редактиране | edit source]

Основи[редактиране | edit source]

regex

В програмирането регулярните изрази (известни още с абревиатурите си regex или regexp) са последователности от символи, които формират модел за търсене, главно за употреба на „шаблонни съвпадения“ (pattern matching) в стрингове, примерно операции, подобни на „намери и замести“ (find and replace). Концепцията е възникнала през петдесете години на 20 век, когато американският математик Стефан Клийни (Stephen Kleene) формулира описанието на един регулярен език, който влиза като инструмент за обща употреба за тектообработка в Unix, ed като редактор и grep (global regular expression print) като филтър.

Всеки символ в един регулярен израз трябва да се тълкува като метасимвол със специално значение, или като регулярен символ с литерално значение. Заедно те могат да бъдат използвани за идентифициране на текстов материал от даден шаблон или обработват n броя инстации от тях, като могат да варират от абсолютна точност на съвпаденията до по-общи сходства в шаблона. Шаблонът сам по себе си е израз, който е проектиран специално за лесна и гъвкава автоматична обработка на текстови файлове, текстови форми или случайни стрингове. За пример можем да вземем следния израз: (?<=\.) {2,}(?=[A-Z]) — открива съвпаденията, маркирани в жълто на картинката, или ^[ \t]+ открива празните места в текста в началото на реда. По-голямата част от компютърните езици поддържат регулярни изрази: Perl, Ruby, AWK, .NET, Java, Python и C++ (от C++11). В много други поддръжката е включена чрез допълнителна библиотека.

История[редактиране | edit source]

Регулярните изрази се зараждат в теорията на автоматите и теорията на формалните езици и двете част от теоретичните компютръни науки. Регулярните изрази описват част от формалните езици и така принадлежат към теоретичната информатика. Те образуват най-долното стъпало от Йерархията на Чомски (тип 3). Използването на регулярни изрази в структурно информационните стандарти за документи и бази данни стартира през 60-те години на 20 век и се разширява през 80-те когато идустриалните стандарти като ISO SGML (описан от ANSI "GCA 101-1983") се обединяват.

Базови концепции[редактиране | edit source]

Регулярният израз, често наричан "pattern" е предназначен за откриване на точни или подобни съвпадения. Макар и да не отговаря на стандартите за регулярни изрази, най честия израз, който всеки е използвал е *.* (означава всичко.всичко) или *.??? (всеки файл с какво да е разширение, но точно 3 символа). Друг пример е със следните 3 стринга "Handel", "Händel", and "Haendel", можем да ги хванем със следния pattern H(ä|ae?)ndel; казваме че израза "хваща" или "мачва" всеки от трите стринга. Повече възможности дават следните операции за конструиране на регулярни изрази:

Boolean "or"(логическо или)

права черта | . Пример: color|colour може да хване "color" или "colour".

Групиране

( ) col(o|ou)r е еквивалентно на color|colour

? * +

  •  ? Въпросителния указва да търси нула или един елемент в стринга. Примерно, colou?r хваща и "color" и "colour".
  • * Звездичката указва да търси нула или повече елемента в стринга. Примерно, ab*c хваща "ac", "abc", "abbc", "abbbc".
  • + Плюс - указва да търси един или повече елемента в стринга. Примерно, ab+c хваща "abc", "abbc", "abbbc", но не и "ac".
  • [ ] хваща единичен символ който е в скобите. Примерно [АВС] хваща "А", "В" или "С" позволява се и серийна обработка( от-до ) [a-z], [a-kq-z] или [1-5].
  • [^ ] Хваща елемент който не е сред изброените(обратно на горното).
  • $ Хваща края на стринг или край на реда.
  • ^ Начало на ред или стринг.
  • {m,n} Хваща дадено множество от n до m пъти. Примерно а{3,5} хваща ааа, аааа, ааааа.
  • { }{ } Конкатенация на стригове. Примерно {а,bb}{g, ff} == ag, aff, bbg, bbff
  • \ Показва на интерпретатора да приема следващия символ буквално \\ \[ \. третира ".", "\" и "[" като символи от стринга
  • \w word - хваща дума. [A-Za-z0-9_]
  • \W Хваща различно от дума.
  • \s Хваща т.н. бели полета (whitespace) интервали, табулации, нов ред.
  • \S Хваща всичко останало освен "бели полета".
  • \d Digits хваща цифри [0-9].
  • \D Изключва цифри също като [^0-9].

Разбира се всички тези правила могат да се групират в по-сложни. Примерно израз за хващане валидността на е-mail ^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$ .

Примери[редактиране | edit source]

PHP[редактиране | edit source]

<?php
// Returns true if "abc" is found anywhere in $string.
ereg("abc", $string);
 
// Returns true if "abc" is found at the beginning of $string.
ereg("^abc", $string);
 
// Returns true if "abc" is found at the end of $string.
ereg("abc$", $string);
 
// Returns true if client browser is Netscape 2, 3 or MSIE 3.
eregi("(ozilla.[23]|MSIE.3)", $_SERVER["HTTP_USER_AGENT"]);
 
// Places three space separated words into $regs[1], $regs[2] and $regs[3].
ereg("([[:alnum:]]+) ([[:alnum:]]+) ([[:alnum:]]+)", $string, $regs);
 
// Put a <br /> tag at the beginning of $string.
$string = ereg_replace("^", "<br />", $string);
 
// Put a <br /> tag at the end of $string.
$string = ereg_replace("$", "<br />", $string);
 
// Get rid of any newline characters in $string.
$string = ereg_replace("\n", "", $string);
?>

JAVA[редактиране | edit source]

package de.vogella.regex.string;
 
public class StringMatcher {
  // Returns true if the string matches exactly "true"
  public boolean isTrue(String s){
    return s.matches("true");
  }
 
  // Returns true if the string matches exactly "true" or "True"
  public boolean isTrueVersion2(String s){
    return s.matches("[tT]rue");
  }
 
  // Returns true if the string matches exactly "true" or "True"
  // or "yes" or "Yes"
  public boolean isTrueOrYes(String s){
    return s.matches("[tT]rue|[yY]es");
  }
 
  // Returns true if the string contains exactly "true"
  public boolean containsTrue(String s){
    return s.matches(".*true.*");
  }
 
  // Returns true if the string contains of three letters
  public boolean isThreeLetters(String s){
    return s.matches("[a-zA-Z]{3}");
    // Simpler from for<br />
 
//    return s.matches("[a-Z][a-Z][a-Z]");
  }
 
  // Returns true if the string does not have a number at the beginning
  public boolean isNoNumberAtBeginning(String s){
    return s.matches("^[^\\d].*");
  }
 
  // Returns true if the string contains a arbitrary number of characters except b
  public boolean isIntersection(String s){
    return s.matches("([\\w&&[^b]])*");
  }
 
  // Returns true if the string contains a number less then 300
  public boolean isLessThenThreeHundret(String s){
    return s.matches("[^0-9]*[12]?[0-9]{1,2}[^0-9]*");
  }

JavaScript[редактиране | edit source]

<code>// The name string contains multiple spaces and tabs,
// and may have multiple spaces between first and last names.
var names = "Harry Trump ;Fred Barney; Helen Rigby ; Bill Abel ; Chris Hand ";
 
var output = ["---------- Original String\n", names + "\n"];
 
// Prepare two regular expression patterns and array storage.
// Split the string into array elements.
 
// pattern: possible white space then semicolon then possible white space
var pattern = /\s*;\s*/;
 
// Break the string into pieces separated by the pattern above and
// store the pieces in an array called nameList
var nameList = names.split(pattern);
 
// new pattern: one or more characters then spaces then characters.
// Use parentheses to "memorize" portions of the pattern.
// The memorized portions are referred to later.
pattern = /(\w+)\s+(\w+)/;
 
// New array for holding names being processed.
var bySurnameList = [];
 
// Display the name array and populate the new array
// with comma-separated names, last first.
//
// The replace method removes anything matching the pattern
// and replaces it with the memorized string—second memorized portion
// followed by comma space followed by first memorized portion.
//
// The variables $1 and $2 refer to the portions
// memorized while matching the pattern.
 
output.push("---------- After Split by Regular Expression");
 
var i, len;
for (i = 0, len = nameList.length; i < len; i++){
  output.push(nameList[i]);
  bySurnameList[i] = nameList[i].replace(pattern, "$2, $1");
}
 
// Display the new array.
output.push("---------- Names Reversed");
for (i = 0, len = bySurnameList.length; i < len; i++){
  output.push(bySurnameList[i]);
}
 
// Sort by last name, then display the sorted array.
bySurnameList.sort();
output.push("---------- Sorted");
for (i = 0, len = bySurnameList.length; i < len; i++){
  output.push(bySurnameList[i]);
}
 
output.push("---------- End");
 
console.log(output.join("\n"));

C#[редактиране | edit source]

static string MDYToDMY(string input)
{
   try {
      return Regex.Replace(input,
            "\\b(?<month>\\d{1,2})/(?<day>\\d{1,2})/(?<year>\\d{2,4})\\b",
            "${day}-${month}-${year}", RegexOptions.None,
            TimeSpan.FromMilliseconds(150));
   }
   catch (RegexMatchTimeoutException) {
      return input;
   }
}

Дефиниция[редактиране | edit source]

  1. \varnothing (празното множество) е регулярен израз.
  2. \varepsilon (празната дума) е регулярен израз.
  3. \forall a_i \in \Sigma е a_i (всеки символ от съответана азбука) регулярен израз.
  4. Ако x и y са регулярни изрази, то (x \cup y) (Обединение), (xy) (Конкатенация) и x^* (оператор-звезда) също са такива.
  5. Нищо друго не е регулярен израз.