regex tutorial, как я могу улучшить это - PullRequest
1 голос
/ 24 февраля 2009

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

<address> <11 * ascii character value>      <11 characters>
00C4F244  75 6C 74 73 3E 3C 43 75 72 72 65  ults><Curre

Я хотел зачеркнуть все до 11 символов в конце и использовал следующее выражение:

"^[0-9A-F+]{8}[\\s]{2}[0-9A-F\\s]{34}"

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

1: с помощью движка регулярных выражений вернуть нужные символы, а не символы, которые я не сделал, и

2: найти способ повторить совпадение для одного значения ascii с последующим пробелом (например, «75» = [0-9A-F] {2} [\ s] {1}?) И повторить этот 11 раз, а не захватывая 34 символа.

Глядя на это снова, проще всего было бы сопоставить последние 11 символов в каждой строке ввода, но это не очень гибко, и в интересах изучения регулярных выражений я хотел бы посмотреть, как вы можете сопоставить с начало последовательности.

Редактировать: Спасибо, ребята, это то, что я хотел:

"(?:^[0-9A-F]{8}  )(?:[0-9A-F]{2} ){11} (.*)"

Хотелось бы, чтобы я стал более зеленым.

Ответы [ 6 ]

5 голосов
/ 24 февраля 2009

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

^.{44}(.{11})
2 голосов
/ 24 февраля 2009

Последние одиннадцать:

...........$

или

.{11}$

Соответствует шестнадцатеричному байту + пробел и повторите одиннадцать раз:

([0-9A-Fa-f]{2} ){11}
1 голос
/ 24 февраля 2009

1) ^ [0-9A-F +] {8} [\ s] {2} [0-9A-F \ s] {34} (. *)

Парены используются для группировки с извлечением. То, как вы его получите, зависит от вашего языкового контекста, но теперь какой-то $ 1 устанавливается для всего после исходного шаблона.

2) ^ [0-9A-F +] {8} [\ s] {2} (?: [0-9A-F \ s]) {11} \ s (. *)

(? :) группирует без извлечения. Итак (?: [0-9A-F \ s]) {11} рассматривает подшаблон там как единицу и ищет его повторное 11 раз.

Между прочим, я предполагаю PCRE.

0 голосов
/ 24 февраля 2009

Если вы используете Perl, вы также можете использовать unpack(), чтобы получить каждый элемент.

my @data;

open my $fh, '<', $filename or die;
for my $line(<$fh>){
  my($address,@list) = unpack 'a8xx(a2x)11xa11', $line;
  my $str = pop @list;

  # unpack the hexadecimal bytes
  my $data = join '', map { pack 'H2',$_ } @list;

  die unless $data eq $str;

  push @data, [$address,$data,$str];
}
close $fh;

Я также пошел дальше и преобразовал 11 шестнадцатеричных кодов обратно в строку, используя pack().

0 голосов
/ 24 февраля 2009

Соответствие концу строки будет

.{11}$

Чтобы соответствовать только концу, вы можете использовать положительный взгляд позади.

"(?<=(^[0-9A-F+]{8}[\\s]{2}[0-9A-F\\s]{34}))(.*?)$"

Это будет соответствовать любому символу до конца строки, при условии, что ему предшествует выражение «смотреть за».

(? <= ....) определяет условие, которое должно быть выполнено, прежде чем сопоставление станет возможным. </p>

Мне немного не хватает времени, но если вы поищите в сети какой-нибудь учебник, содержащий слова "regex" и "lookbehind", вы найдете хороший материал (если учебник по регулярным выражениям смотрит вперед / назад, обычно будет довольно полным и продвинутым).

Еще один совет - взять инструмент обучения регулярным выражениям и поиграть с ним. Взгляните на этого превосходного Regex конструктора .

0 голосов
/ 24 февраля 2009

Адрес и значение ascii char все шестнадцатеричные, поэтому:

^ [0-9A-F \ s] {42}

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