извлечение первой буквы строки с помощью регулярного выражения - PullRequest
2 голосов
/ 20 июля 2010

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

[2010-01-15 06: 18: 10.203] [0x00001388] [SHDNT] Обратный отсчет выключения = 2/5

[2010-01-15 06: 18: 11.203] [0x00001388] [SHDNT] Обратный отсчет отключения = 3/5

И я хочу иметь возможность найти в моем поиске '[' и ']' вокруг даты. Я подумал о том, чтобы найти '[' с использованием некоторых критериев, таких как ('[', за которыми следуют [0-9] [0-9], означающие две цифры) и ']' с помощью (']' исходящий текст. [0-9] [0-9] 'означает точку и 3d-цифры).

Я пробовал это, но выдает ошибку \ [(? = [0-9] [0-9]) для первого поиска. Разве не позволяет мне поставить? сразу после скобки.

Как мне выполнить поиск?

Заранее спасибо

ИЗМЕНЕНО ДЛЯ ДОБАВЛЕНИЯ

Чтобы было ясно, я не использую RegEx с любым языком программирования. Я использую текстовый редактор, который имеет функцию поиска и замены, которая позволяет поиск по шаблону. Поэтому я хочу снять квадратные скобки вокруг даты. Но не надо ничего менять в моем файле.

Ответы [ 7 ]

2 голосов
/ 20 июля 2010

Следующее регулярное выражение:

^\[([^\]]+)\]

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

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

^ = beginning of line/string
\[, \] = literal [ and ] characters
() = signifies a group to capture
[^\]] = matches any character _except_ a close bracket
        (this keeps the match from being too greedy)
+ = one or more of the previous

РЕДАКТИРОВАТЬ: Это предполагает, что ваше средство регулярных выражений поддерживает группы (что большинство делает). Самый простой способ объяснить группы - это просто показать вам, как они работают с одним таким движком. В интерпретаторе Python:

>>> import re
>>> s = '[2010-01-15 06:18:10.203] [0x00001388] [SHDNT] ...'
>>> r = re.compile(r'^\[([^\]]+)\]')
>>> m = r.search(s)

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

>>> m
<_sre.SRE_Match object at 0x1004d9558>

Чтобы получить весь набор текста, который был сопоставлен, соглашение Python должно вызывать group() для объекта сопоставления:

>>> m.group()
'[2010-01-15 06:18:10.203]'

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

>>> m.group(1)
'2010-01-15 06:18:10.203'

Если я выполняю замену вместо поиска, я использую функцию sub. Sub принимает строку, которую я хочу заменить на совпадение full , после чего следует строка ввода и возвращает строку с выполненной заменой, если совпадение было найдено:

>>> r.sub('spam spam spam', s)
'spam spam spam [0x00001388] [SHDNT] ...'

Однако строка замены поддерживает escape-последовательности, которые ссылаются на конкретные значения групп, захваченных совпадением. Замена группы обозначена \N, где N - номер группы. Следовательно:

>>> r.sub(r' \1 ', s)
' 2010-01-15 06:18:10.203  [0x00001388] [SHDNT] ...'

что вы и хотите.

2 голосов
/ 20 июля 2010

будь проще. Там нет необходимости использовать регулярное выражение. Если часть даты / времени - это все, что вам нужно, используйте поля и разделители полей. вот выражение awk. Просто распечатайте первый столбец (закрывающая квадратная скобка как разделители полей.)

$ cat file
[2010-01-15 06:18:10.203] [0x00001388] [SHDNT] Shutdown Count Down = 2/5
[2010-01-15 06:18:11.203] [0x00001388] [SHDNT] Shutdown Count Down = 3/5

$ awk -F"]" '{print $1"]"}' file
[2010-01-15 06:18:10.203]
[2010-01-15 06:18:11.203]

или просто распечатайте поля 1 и 2, используя пробелы в качестве разделителей

$ awk '{print $1,$2}' file
[2010-01-15 06:18:10.203]
[2010-01-15 06:18:11.203]

Обновление: чтобы снять квадратные скобки, просто используйте gsub() или sub() в полях 1 и 2

$ awk '{gsub(/^\[/,"",$1);gsub(/\]$/,"",$2)}1' file
2010-01-15 06:18:10.203 [0x00001388] [SHDNT] Shutdown Count Down = 2/5
2010-01-15 06:18:11.203 [0x00001388] [SHDNT] Shutdown Count Down = 3/5
1 голос
/ 20 июля 2010

Я не уверен, что вам нужно использовать в своих регулярных выражениях утверждения типа lookahead или lookbehind:

 sarnold@haig:/tmp$ cat date.pl
 #!/usr/bin/perl -w

 while(<>) {
     /^(\[\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d\.\d\d\d\])/;
     print "$1\n";
 }
 sarnold@haig:/tmp$ cat data
 [2010-01-15 06:18:10.203] [0x00001388] [SHDNT] Shutdown Count Down = 2/5
 [2010-01-15 06:18:11.203] [0x00001388] [SHDNT] Shutdown Count Down = 3/5
 sarnold@haig:/tmp$ ./date.pl data
 [2010-01-15 06:18:10.203]
 [2010-01-15 06:18:11.203]

Я не могу сказать из вашего описания, если вы действительно хотите [ и ] около вашей даты или если вы не хотите их. Если вам не нужны квадратные скобки, переместите их за пределы скобок:

     /^\[(\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d\.\d\d\d)\]/;

sarnold@haig:/tmp$ ./date.pl data
2010-01-15 06:18:10.203
2010-01-15 06:18:11.203

Обратите внимание, что я также закрепил регулярное выражение в начале строки, в случае, если выходные данные включают в себя дату и время в скобках где-то еще. Кроме того, я переопределил дату и время по сравнению с вашим примером. Считайте, что это паранойя. Если вы хотите заменить \d\d\d\d на \d{4}, вы можете, но в этом примере я нахожу более длинную форму более читабельной.

0 голосов
/ 20 июля 2010

Ах, спасибо за ваш дополнительный комментарий в одном из ответов.

В vim я бы, вероятно, использовал инструмент визуального выбора: поместите курсор на первый [, введите ^V, G (чтобы добраться до конца файла), затем x для удалить столбец. Затем повторите с первым символом ], ^V, G (но G поместит курсор на неправильный символ - поэтому используйте l или клавишу со стрелкой вправо, чтобы перейти к ]), а затем введите x, чтобы удалить столбец.

Если бы он не выстраивался идеально в столбцах (возможно, в .203 могло бы быть меньше символов, скажем, .2), тогда я бы сделал это:

:%s/^\[//
:%s/\(\d\)] /\1 /

Отмечая, конечно, что второе регулярное выражение является гораздо более хрупким; он удалит первый ], который находится между цифрой и пробелом в каждой строке. Non-vim не будет так раздражать по поводу экранирования ( и ).

Конечно, если вы не используете vi-клон, надеюсь, это может перевести достаточно хорошо. :)

0 голосов
/ 20 июля 2010

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

C # пример:

LINQ:

string[] firsts = myFile.ReadAllLines().Select(f=>f[0]);

Цикл с foreach:

string[] allLines = myFile.ReadAllLines();
foreach (string line in allLines)
{
    char firstChar= line[0];
    Console.WriteLine("First char: " + firstChar.ToString());

    if (firstChar = '[')
    {
       int closing = line.IndexOf(']');
       string textWithin = line.SubString(0, closingSquare-1);
       Console.WriteLine("Found this text within the square brackets: " + textWithin);
    }
}
0 голосов
/ 20 июля 2010

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

$ cut -c 2-24 <<EOF
[2010-01-15 06:18:10.203] [0x00001388] [SHDNT] Shutdown Count Down = 2/5
[2010-01-15 06:18:11.203] [0x00001388] [SHDNT] Shutdown Count Down = 3/5
EOF

2010-01-15 06:18:10.203
2010-01-15 06:18:11.203
0 голосов
/ 20 июля 2010

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

  1. ^ соответствует началу строки.
  2. . соответствует любому одному символу.
  3. *? соответствует предыдущему нулю или больше раз НЕ ЖЕЛЕЗНО, что означает, что не требуется больше, чем нужно, чтобы остальное совпадение регулярного выражения.

Сложите это вместе, и вы получите ^.*?\], который соответствует от начала строки до первого ], который он видит.

РЕДАКТИРОВАТЬ: Только что видел ваш ответ Ghostdog, который прояснил проблему. Еще проще сопоставить всю дату с фигурными скобками. Получив это, просто замените всю строку на себя, за исключением первого и последнего символа. Я не знаю, какой язык вы используете, но в Python это будет примерно так:

new_string = re.sub(r'^.*?\]',original_string,lambda m:m.group()[1:-1])
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...