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

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

В информатиката регулярен израз (на английски: 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. Нищо друго не е регулярен израз.