Стандартный Regex по сравнению с Python regex несоответствие

Я читаю книгу, и они обеспечивают пример того, как соответствовать данной строке регулярным выражениям. Вот их пример:

b*(abb*)*(a|∊) - Strings of a's and b's with no consecutive a's.

Теперь я попытался преобразовать его в Python как так:

>> p = re.compile(r'b*(abb*)*(a|)') # OR
>> p = re.compile(r'b*(abb*)*(a|\b)')

# BUT it still doesn't work
>>> p.match('aa')
<_sre.SRE_Match object at 0x7fd9ad028c68>

Мой вопрос является двукратным:

  1. Каков эквивалент эпсилона в Python, чтобы заставить вышеупомянутый пример работать?
  2. Кто-то может объяснить мне, почему теоретический или стандартный способ сделать регулярные выражения не работает в Python? Это могло бы иметь некоторое отношение к самому длинному по сравнению с самым коротким соответствием?

Разъяснение: Для людей, спрашивающих, что стандарт regex - это - стандарт теории формальных языков: http://en.wikipedia.org/wiki/Regular_expression#Formal_language_theory

5
задан Andriy Drozdyuk 12 January 2010 в 15:44
поделиться

7 ответов

Одним из решений является изменение графических объектов, созданных bar3 . Во-первых, вы должны получить ручки, возвращенные из bar3 :

h = bar3(z);

В вашем случае, h будет 3-элементный вектор ручек, по одной для каждого набора цветных полос. Следующий код должен сделать ячейки с нулем невидимыми:

for i = 1:numel(h)
  index = logical(kron(z(:, i) == 0, ones(6, 1)));
  zData = get(h(i), 'ZData');
  zData(index, :) = nan;
  set(h(i), 'ZData', zData);
end

И вот иллюстрация (с обязательными кругами свободной руки):

enter image description here

Как это работает...

Если вектором количества ячеек является N-1 , то bar3 нанесет на график 6 * N прямоугольные фрагменты (т.е. 6 грани кубоида для каждого ячейки). Свойство «ZData» для каждого набора объектов-исправлений в h будет иметь значение (6 * N) -by-4 , поскольку для каждой прямоугольной грани имеется 4 угла. Таким образом, каждый кластер 6 строк свойства «ZData» представляет собой набор z-координат для 6 граней одной ячейки.

Приведенный выше код сначала создает логический вектор с единицами везде, где число элементов равно 0, затем реплицирует каждый элемент этого вектора 6 раза с помощью функции kron . Этот индекс становится индексом для строк свойства «ZData» , и этот индекс используется для установки координат z в nan для исправлений пустых ячеек. Это приведет к тому, что исправления не будут визуализированы.


EDIT:

Вот немного измененная версия кода, которая делает его более общим, извлекая высоту полосы из свойства «ZData» выводимых на печать полос , так что все, что нужно для ее работы, это ручки, возвращенные из bar3 . Я также завернул код в функцию (sans error and input check):

function remove_empty_bars(hBars)
  for iSeries = 1:numel(hBars)
    zData = get(hBars(iSeries), 'ZData');  % Get the z data
    index = logical(kron(zData(2:6:end, 2) == 0, ones(6, 1)));  % Find empty bars
    zData(index, :) = nan;                 % Set the z data for empty bars to nan
    set(hBars(iSeries), 'ZData', zData);   % Update the graphics objects
  end
end
-121--3095754-

Проблема со списком > в том, что для изменения размера матрицы необходимо изменить размер каждой строки.

Если вы хотите использовать разреженную матрицу, или, может быть, бесконечную матрицу, вы можете сделать что-то вроде:

class SparseMatrix<X> {
  private Map<Coord, X> values = new HashMap<Coord, X>();

  public SparseMatrix() {
  }

  public X get(int x, int y) {
     return values.put(new Coord(x,y)); // null if there's no value
  }

  public void set(int x, int y, X value) { // you can use null (like in a List)
     values.set(new Coord(x,y), value);
  }

  private static class Coord {
    int x; int y;
    public Coord(int x, int y) {
       this.x = x;
       this.y = y;
    }

    @Override
    public boolean equals(Object other) {
       if (other instance of Coord) {
          Coord o = (Coord) other;
          return o.x == x && o.y == y;
       }
       return false;
    }

    @Override
    public int hashCode() {
       return o.x + o.y; // or some more clever implementation :)
    }

  }
}

Edit: Apache Commons HashCodeBuilder является отличным инструментом для создания хэш-кодов.

-121--2717465-

Спасибо за ответы. Я чувствую, что каждый ответ был частью ответа. Вот что я искал. Символ

  1. ? является просто кратким для (something 'start) . Таким образом, (a 'start) можно переписать как a? . Таким образом, пример становится:

     b * (abb *) * a?
    

    В питоне мы бы написали:

     p = re.compile (r '^ b * (abb *) * a? $')
    
  2. Прямая трансляция синтаксиса регулярного регулярного выражения в python (т.е. копирование и вставка) не работает, потому что python соответствует самой короткой подстроке (если символы $ или ^ отсутствуют), в то время как теоретические регулярные выражения соответствуют самой длинной начальной подстроке .
    Так, например, если у нас была последовательность:

     s = 'aa'
    

    Наш учебник regex b * (abb *) * a? не будет соответствовать ему, потому что у него есть два а. Однако, если скопировать его прямо в python:

     > > p = re.compile (r 'b * (abb *) * a?')
    > > bool (p.match (s))Правда
    

    Это происходит потому, что наш регекс соответствует только подстроке «a» нашей последовательности «aa».
    Для того, чтобы сказать Питону, чтобы сделать совпадение в целом ряде мы должны сказать ему, где начало и конец последовательности, с ^ и $ соответственно:

     > > p = re.compile (r '^ b * (abb *) * a? $')
    > > bool (p.match (s))
    Ложный
    

    Обратите внимание, что python regex match () совпадает с началом последовательностей, поэтому он автоматически принимает ^ в начале. Однако функция search () не выполняет, и поэтому мы сохраняем ^ .
    Так например:

     > > s = 'aa'
    > > p = re.compile (r 'b * (abb *) * a? $')
    > > bool (p.match (s))
    Ложь # Правильно
    > > bool (p.search (s))
    True # Неверно - поиск проигнорировал первый «» а
    
5
ответ дан 18 December 2019 в 08:28
поделиться

На самом деле, пример работает просто отлично ... до мельчайших деталей. Я бы написал:

>>> p = re.compile('b*(abb*)*a?')
>>> m = p.match('aa')
>>> print m.group(0)
'a'
>>> m = p.match('abbabbabababbabbbbbaaaaa')
>>> print m.group(0)
abbabbabababbabbbbba

Обратите внимание, что группа 0 возвращает ту часть строки, которой соответствует регулярное выражение.

Как видите, выражение совпадает с последовательностью a и b без повторения a. Если действительно хотите проверить всю строку, нужно немного изменить:

>>> p = re.compile('^b*(abb*)*a?$')
>>> m = p.match('aa')
>>> print m
None

^^ и $ форсированное распознавание начала и конца строки.

Наконец, можно объединить оба метода, используя первое регулярное выражение, но тестирование в конце:

>>> len(m.group(0)) == len('aa')

Added: Для второй части ОТ, как мне кажется, нет никакого несоответствия между стандартным регексом и реализацией питона. Конечно, нотация немного отличается, а реализация питона предполагает некоторые расширения (как и большинство других пакетов).

5
ответ дан 18 December 2019 в 08:28
поделиться

"Пул" содержит список доступных "потоков", готовых к использованию, в то время как "нерест" относится к фактическому созданию нового потока.

Полезность "объединения потоков" заключается в "меньшем времени использования": исключаются накладные расходы времени создания.

В терминах "какой лучше" - это зависит. Если накладные расходы времени создания являются проблемой, используйте Thread-pooling. Это распространенная проблема в средах, где требуется выполнение большого количества "кратковременных задач".


Как указывали другие пользователи, существует "накладные расходы на управление" для Thread-Pooling: это минимально, если правильно реализовано. Например, ограничение количества потоков в пуле является тривиальным.

-121--1299633-

Ваша вторая попытка должна стать подходящей заменой эпсилону, насколько я понимаю, хотя раньше я никогда не видел эпсилона в регексе.

Для чего это стоит, ваш шаблон соответствует 'a'. То есть это совпадение:

  • ноль или более " b " s (выбор нуля)
  • ноль или более " (abb *) " s (выбор нуля)
  • один " a " или слово, заканчивающееся (выбор a).

Как указал Джонатан Файнберг, если вы хотите обеспечить соответствие всей строки, вы должны привязать начало ( '^' ) и конец ( '$' ) вашего регекса. Также следует использовать необработанную строку при построении регексов в python: r 'my regex'. Это предотвратит чрезмерную обратную косую черту, избежав путаницы.

1
ответ дан 18 December 2019 в 08:28
поделиться

Во втором комментарии по адресу ip2long в руководстве по функциям имеется функция ip2long6 для IPv6 (далее).

-121--2386021-
  • Это не совсем правильно. Пожалуйста, смотрите на алгоритм: текст высокого звука http://img532.imageshack.us/img532/1017/cache.png
  • решение по доверенности дружелюбно, вы можете использовать контроль Тайника: полномочие - подтверждает, чтобы вынудить тайники повиноваться любой информации о свежести, которую вы даете им о ресурсе (только относится к shared'proxy тайникам)

, Вот функция, которая могла бы помочь:

function isModified($mtime, $etag) {
    return !( (
        isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])
        && 
        strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) >= $mtime
    ) || (
        isset($_SERVER['HTTP_IF_NONE_MATCH'])
        && 
        $_SERVER['HTTP_IF_NONE_MATCH'] == $etag
    ) ) ;
}

я предлагаю, чтобы вы смотрели на следующую статью: http://Обновление www.peej.co.uk/articles/http-caching.html

:

[AlexV] Возможно ли даже получение if-none-match AND if-modified-так как одновременно?

Вы определенно можете иметь оба набора. Однако

Если ни один из тэгов объекта не совпадает, сервер МОЖЕТ выполнить запрошенный метод, как если бы поле заголовка If-None-Match не существовало, но также ДОЛЖЕН игнорировать любые поля (поля ) заголовка If-Modified-Since в запросе. То есть, если ни один объект не тэгов совпадать, то сервер НЕ ДОЛЖЕН возвращать ответ 304 (Not Modified).

RFC2616 # 14,26

Примерные значения (W означает «слабый»; Подробнее читайте в RFC2616 # 13,3,3 ):

If-None-Match: "xyzzy", "r2d2xxxx", "c3piozzzz"
If-None-Match: W/"xyzzy", W/"r2d2xxxx", W/"c3piozzzz"
If-Modified-Since: Sat, 29 Oct 1994 19:43:31 GMT
If-None-Match: *

В частном случае значение «*» соответствует любому текущему объекту ресурса.

-121--3560079-

1

  • Используйте bool (p.match ('aa')) , чтобы проверить, соответствует ли regexp

  • p = re.compile ('b * (abb *) * a? $')

  • \b границе последовательности; место между \w и \W (символы слова и непервичные символы)

2

Regexp вполне стандартно для питона. Тем не менее, каждый язык имеет некоторый вкус их, они не на 100% портативны. Есть незначительные различия, которые вы должны искать до использования regexp на любом конкретном языке.

Добавление

\epsilon не имеет специального символа в python. Это пустой набор символов.

В вашем примере a |\epsilon эквивалентен (a |) или только a? . После чего $ обязательно соответствует концу последовательности.

3
ответ дан 18 December 2019 в 08:28
поделиться

Я не совсем уверен, как матч работает в Python, но я думаю, что вам может потребоваться добавить ^ .... $ до вашего RE. Соответствие Regexp обычно соответствует подтяжкам, и он находит наибольшее совпадение в случае p.match ('aa'), который "A" (вероятно, первый). ^ ... $ Убедитесь, что вы соответствуете всей строке, которая я считаю то, что вы хотите.

Теоретический / стандартный REG EXPS предполагает, что вы всегда соответствуете всей строке, поскольку вы используете его, чтобы определить язык строк, которые совпадают, не найдите подстроку в входной строке.

3
ответ дан 18 December 2019 в 08:28
поделиться

Вы соответствуете, потому что ваше Regeex соответствует любому сегменту нулевой ширины любого текста образец. Вам нужно якорь Ваше регулярное выражение. Вот один из способов сделать это, используя ноль-ширину Lookahead Assertion:

re.compile(r'^(a(?!a)|b)*$')
1
ответ дан 18 December 2019 в 08:28
поделиться

Проблема с вашим выражением является то, что она соответствует пустой строке, что означает, что если вы сделаете:

>>> p = re.compile('b*(abb*)*(a|)')
>>> p.match('c').group(0)
''

и поскольку Re.match пытаются сопоставить начало строки, вы должны сказать ему, чтобы сопоставить его до конца строки. Просто используйте $ для этого -

>>> p = re.compile(r'b*(abb*)*(a|)$')
>>> print p.match('c')
None
>>> p.match('ababababab').group(0)
'ababababab'

- вы, возможно, отметили, что я использовал R'Pattern 'вместо «картина» больше на это здесь (первый абзацы)

1
ответ дан 18 December 2019 в 08:28
поделиться
Другие вопросы по тегам:

Похожие вопросы: