Соответствие регулярному выражению до появления строки

Итак, у меня есть этот файл из 10 000+ строк сообщений с игрового сервера, например:

11.07.23 08:40:16 [INFO] NC: Нарушение перемещения: wolfman98 от yasmp (-90,8, 64,0, 167,5) до (-90,7, 64,0, 167,3) расстояния (0,0, 0,0, 0,2)

11.07.23 10:57:44 [INFO] NC: Нарушение перемещения: AKxiZeroDark от yasmp (-1228.3, 11.2, 1098.7) до (-1228.3, 11.2, 1098.7) расстояния (0.0, 0.0, 0.0)

Текущий код регулярного выражения, который у меня есть: \d{1,4}\.\d{1}, который до сих пор соответствует всему, что выделено жирным шрифтом:

11.07.23 08:40:16 [INFO] NC: Нарушение перемещения: wolfman98 from yasmp (-90,8, 64,0, 167,5 ) до (-90,7, 64,0, 167,3) расстояния (0,0, 0,0 , 0,2)

У меня возникли проблемы с поиском способа получить часть, которая говорит только:

(-1228.3, 11.2, 1098.7) to (-1228.3, 11.2, 1098.7)

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

11.07.23 08:40:16 [INFO] NC: Перемещение нарушения: wolfman98 из yasmp (-#, #, #) в (-#, #, #) расстояние (0,0, 0,0, 0,2)

11.07.23 10:57:44 [INFO] NC: Перемещение нарушения: AKxiZeroDark из yasmp (-#, #, #) в (-#, #, #) расстояние (0,0, 0,0, 0,0)

И немного дополнительной информации, числа могут быть как отрицательными, так и нет, в диапазоне от 1,0 до 1234,0 цифр, поэтому мне нужна помощь в сопоставлении перед расстоянием до слова снова.

РЕДАКТИРОВАТЬ: Или даже было бы хорошо, если бы все это не появлялось:

11.07.23 08:40:16 [ИНФО] NC: Нарушение перемещения: wolfman98 from yasmp Distance (0.0, 0.0, 0.2)

11.07.23 10:57:44 [INFO] NC: Нарушение перемещения: AKxiZeroDark from yasmp Distance (0.0, 0.0, 0.0)


person DreamPhreak    schedule 13.08.2011    source источник


Ответы (4)


Довольно странным регулярным выражением, которое расширяет регулярное выражение для сопоставления чисел, будет \((?:-?\d{1,4}\.\d{1}(?:, |\))){3} to \((?:-?\d{1,4}\.\d{1}(?:, |\))){3}(?= distance). Давайте немного сломаем это.

Он состоит из двух групп, идентичных двум группам чисел в скобках: \((?:-?\d{1,4}\.\d{1}(?:, |\))){3}. Регулярное выражение теперь допускает необязательный - перед числом, что делает число совпадающим с -?\d{1,4}\.\d{1}. После каждого числа стоит либо запятая, либо скобка, поэтому для повторения совпадения чисел нам это тоже нужно: (?:, |\)). Затем ко всему этому зверю добавляется префикс \(, чтобы получить открывающую скобку числовой группы. Это регулярное выражение повторяется дважды, чтобы получить две группы чисел с совпадением to между ними.

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

Я использовал группы без захвата (вещь (?: ... )), потому что я не знаю, что вы хотите делать с захватами.

Я проверил это на двух ваших примерах строк файла журнала, используя perl 5.12.2, и, похоже, это работает.

person aparker42    schedule 13.08.2011
comment
Затем вы можете использовать это регулярное выражение для замены числа хешами, извлекая теперь совпадающие числа, заменяя числа хэшами, а затем реконструируя строку журнала: perl -ne '/^(.*)(\((?:-?\d{1,4}\.\d{1}(?:, |\))){3} to \((?:-?\d{1,4}\.\d{1}(?:, |\))){3})(?= distance)(.*)$/ && do { my ($pre, $no_numbers, $post) = ($1, $2, $3); $no_numbers =~ s/\d+\.\d+/#/g; print "$pre$no_numbers$post\n"; }' - person aparker42; 13.08.2011

Вам нужно сопоставить начало (, которое открывает последовательность, до конца ) перед расстоянием.

Непроверенное, возможно, слишком широкое регулярное выражение может быть: \([-0-9., ]+\) to \([-0-9., ]+\), но оно может соответствовать вещам, которые вам не нужны.

person Vatine    schedule 13.08.2011
comment
Вам также понадобится пробел между парами квадратных скобок, чтобы он совпадал, т. Е. \([-0-9., ]+\) to \([-0-9., ]+\). - person drf; 13.08.2011

/(?:\-|\b)\d{1,4}.\d{1}\b(?=.*distance)/

Соответствует нужным числам (проверено в PHP).

person nobody    schedule 13.08.2011

Звучит как работа для perl:

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

my $rx = qr/\([0-9,\.\- ]+\)/;

while (<>) {
    s/ $rx to $rx( distance $rx\s*)$/$1/;
    print;
}

Использование: script.pl input.txt > output.txt

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

perl -pwe 's/ \([^)]+\)//; s/ \([^)]+\)//;' input.txt 
person TLP    schedule 13.08.2011