Как мне сопоставить слово, за которым следует новая строка, а затем перехватить следующую строку до новой строки? - PullRequest
1 голос
/ 23 июля 2011

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

OR
   field.lastupdate > DATE_SUB(CURDATE(), INTERVAL 31 DAY))
AND
  *some more code*

Я хочу удалить ИЛИ (и это тоже может быть И) до символа новой строки, в этом примере, после второй круглой скобки.Однако я хочу оставить оставшуюся часть кода без изменений.

Я думаю, что регулярное выражение должно быть простым, за исключением того, как игнорировать символ новой строки после ИЛИ, но останавливаться на следующем символе новой строки?

Я должен отметить, что некоторые строки даты, которые я хочу удалить, заканчиваются ";", который я не хочу удалять.

Вот более полный пример, который, я надеюсь, прояснит ситуацию:

OR
        x.is_deleted = 0
OR
        x.lastupd > DATE_SUB(CURDATE(), INTERVAL 31 DAY))
AND
        (j.active = 1
OR
        j.is_deleted = 0
OR
        j.lastupd > DATE_SUB(CURDATE(), INTERVAL 31 DAY));

Итак, вы видите, что я хочу оставить первое «ИЛИ» и следующую за ним строку,

удалить второе «ИЛИ» и строку, следующую за ним.

Сохраните «И» и следующую за ней строку, а также следующее «ИЛИ» и соответствующую ему строку.

А затем удалите последнее «ИЛИ» и его строку, оставляя последний «;».

Ответы [ 3 ]

3 голосов
/ 23 июля 2011
$sql =~ s/\b(?:OR|AND)[ \t]*[\n\r]+(?=.*DATE).*(?<![;\s])//mg;

Удаляет OR (или AND) и содержимое в следующей строке (если оно содержит DATE), за исключением возможного окончания ;.

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

Пример на http://ideone.com/0Lbxp

0 голосов
/ 23 июля 2011

Иногда простые решения являются лучшими.Этот сценарий будет только (повторно) печатать строки, которые не соответствуют описанию строк, которые вы хотели удалить.Он напечатает конечную точку с запятой ;, если найдет ее.Он сохранит строки как прочитанные.

Он не основан на пустых строках и на том, что ни в каких строках нет слова DATE_SUB.

Использование:

$ script.pl input.txt > output.txt

Код:

use strict;
use warnings;
use ARGV::readonly;

while (my $line1 = <>) {
    if ($line1 =~ /^\s*(OR|AND)\s*$/) {
        my $line2 = <>;
        if ($line2 =~ /DATE_SUB/) {
            if ($line2 =~ /;\s*$/) {
                print ";\n";
            }
        } else {
            print $line1, $line2;
        }
    } else {
        print $line1;
    }
}
0 голосов
/ 23 июля 2011

Ну, я не знаю, есть ли только одно предложение после предложения, имеющее ИЛИ / И.

Идея состоит в том, чтобы отслеживать флаг, который сообщит вам, что вы встретили OR / AND в предыдущем предложении.

Возможно, вы можете сделать что-то подобное.

open(FPTR, "infilename")
    or die "\nCan't open $filename for reading: $!\n";
open(OUT, ">outfilename")
    or die "\nCan't open $OUT for writing: $!\n";
my $st=0;
while(<FPTR>)
{
if($_ =~ m/OR$/ || $_ =~ m/AND$/) {
    $st=1;
}
elsif($st==1 $$ **match to your sentence**) {
    $st=0; 
    next;#since you want to remove the line followed by line containing OR/AND

}
else {
    print OUT $_;
    #i'm not sure if here also you need to set $st=0;
}

}

close(FPTR);
close(OUT);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...