Regex: как определить нечетное / четное число случаев символа, предшествующего данному символу?

2008 SQLServer теперь имеет тип данных 'даты', который содержит только дату без компонента времени. Любой использующий SQLServer 2008 и вне может сделать следующее:

SELECT CONVERT(date, GETDATE())
13
задан Cœur 30 April 2017 в 12:48
поделиться

8 ответов

Это правда, что регулярные выражения не могут считаться, но они можно использовать , чтобы определить, есть ли что-то четное или нечетное. Уловка в этом случае состоит в том, чтобы исследовать кавычки после трубы, а не перед ней.

str = str.replace(/\|(?=(?:(?:[^"]*"){2})*[^"]*$)/g, "OR");

Разбивая это на части, (?: [^ "] *") {2} соответствует следующей паре кавычек, если она есть, вместе с промежуточными кавычками. После того, как вы проделаете это столько раз, сколько сможете (что может быть равно нулю), [^ " ] * $ использует все оставшиеся не заключенные в кавычки до конца строки.

Конечно, это предполагает, что текст имеет правильный формат. Он также не решает проблему экранированных кавычек, но может, если вам это нужно.

11
ответ дан 1 December 2019 в 22:24
поделиться

Регулярные выражения не учитываются. Для этого нужны парсеры.

5
ответ дан 1 December 2019 в 22:24
поделиться

Вы можете найти Perl FAQ по этому вопросу актуально.

#!/usr/bin/perl

use strict;
use warnings;

my $x = qq{"this | that" | "the | other"};
print join('" OR "', split /" \| "/, $x), "\n";
4
ответ дан 1 December 2019 в 22:24
поделиться

Возможно, вы ищете что-то вроде этого:

(?<=^([^"]*"[^"]*")+[^"|]*)\|
0
ответ дан 1 December 2019 в 22:24
поделиться

Всем спасибо. Приносим извинения за то, что не упомянули, что это в javascript, и что термины не нужно цитировать, и может быть любое количество цитируемых / некотируемых терминов, например:

"this | that" | "the | other" | yet | another  -> "this | that" OR "the | other" OR yet OR another 

Дэниел, кажется, что это примерно, то есть в основном соответствие / массажная петля. Спасибо за подробное объяснение. В js это выглядит как разбиение, цикл forEach для массива терминов, отправка термина (после изменения | термина на OR) обратно в массив и повторное соединение.

0
ответ дан 1 December 2019 в 22:24
поделиться

Вам не нужно считать, потому что вы не вкладываете кавычки. Это будет делать:

#!/usr/bin/perl

my $str = '" this \" | that" | "the | other" | "still | something | else"';
print "$str\n";

while($str =~ /^((?:[^"|\\]*|\\.|"(?:[^\\"]|\\.)*")*)\|/) {
        $str =~ s/^((?:[^"|\\]*|\\.|"(?:[^\\"]|\\.)*")*)\|/$1OR/;
}

print "$str\n";

Теперь давайте объясним это выражение.

^  -- means you'll always match everything from the beginning of the string, otherwise
      the match might start inside a quote, and break everything

(...)\|   -- this means you'll match a certain pattern, followed by a |, which appears
             escaped here; so when you replace it with $1OR, you keep everything, but
             replace the |.

(?:...)*  -- This is a non-matching group, which can be repeated multiple times; we
             use a group here so we can repeat multiple times alternative patterns.

[^"|\\]*  -- This is the first pattern. Anything that isn't a pipe, an escape character
             or a quote.

\\.       -- This is the second pattern. Basically, an escape character and anything
             that follows it.

"(?:...)*" -- This is the third pattern. Open quote, followed by a another
              non-matching group repeated multiple times, followed by a closing
              quote.

[^\\"]    -- This is the first pattern in the second non-matching group. It's anything
             except an escape character or a quote.

\\.       -- This is the second pattern in the second non-matching group. It's an
             escape character and whatever follows it.

Результат будет следующим:

" this \" | that" | "the | other" | "still | something | else"
" this \" | that" OR "the | other" OR "still | something | else"
1
ответ дан 1 December 2019 в 22:24
поделиться

Другой подход (похожий на рабочий ответ Алана М):

str = str.replace(/(".+?"|\w+)\s*\|\s*/g, '$1 OR ');

Часть внутри первой группы (с интервалом для удобочитаемости):

".+?"  |  \w+

... в основном означает, что-то процитированное или слово. Остаток означает, что за ним следует "|" заключен в необязательный пробел. Замена состоит в том, что первая часть («$ 1» означает первую группу), за которой следует «ИЛИ».

1
ответ дан 1 December 2019 в 22:24
поделиться

@Alan M, works nicely, escaping not necessary due to the sparseness of sqlite FTS capabilities.

@epost, accepted solution for brevity and elegance, thanks. it needed to merely be put in a more general form for unicode etc.

(".+?"|[^\"\s]+)\s*\|\s*
0
ответ дан 1 December 2019 в 22:24
поделиться
Другие вопросы по тегам:

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