LINUX.ORG.RU

Поиск указанного количества подстрок при помощи grep

 ,


0

1

Приветствую.

Есть файл со множеством уравнений - как сложных, так и простых. Например:
1. A0 = A1 + A2
2. A0 = (A1 + A2) * (A3 + A4)
3. A0 = (A1 + A2) + (A3 + A4)

Пытаюсь сконструировать регулярное выражение для выделения строк с чётко указанным количеством совпадений. Пробовал всякие варианты с «{n,}» и «\1». Не едут лыжи.
Что хочется, пример:

1. grep -E хитрое_выражение{1} - выводится только первое уравнение;
2. grep -E хитрое_выражение{2} - выводится только второе уравнение;
3. grep -E хитрое_выражение{3} - выводится только третье уравнение;
4. grep -E хитрое_выражение{2,} - выводится только второе и третье уравнения.
И т. д.

ПС. на regex101 ходил, и по шагам отлаживал разные задумки и ман к grep перечитывал. Может какую-то мелочь упускаю из виду?
ППС. использование grep не принципиально, главное - результат. Я уже думаю просто программу написать для этой задачи.

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



Последнее исправление: smalcom (всего исправлений: 1)

вообще ничего не понятно. сначала ты пишешь:

Пытаюсь сконструировать регулярное выражение для выделения строк с чётко указанным количеством совпадений

количеством совпадений

а потом:

  1. grep -E хитрое_выражение{1} - выводится только первое выражение;

так тебе выражение по номеру нужно или количество совпадений? и что ты понимаешь под «выражением»?

anonymous
()

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

firkax ★★★★★
()

выводится только первое выражение;

grep lalala | head -n 1

выводится только второе выражение;

grep lalala | head -n 2 | tail -n 1

выводится только третье выражение;

grep lalala | head -n 3 | tail -n 1

выводится только второе и третье выражения.

grep lalala | head -n 3 | tail -n 2

Вместо head можно делать grep lalala -m 2

crutch_master ★★★★★
()
Последнее исправление: crutch_master (всего исправлений: 1)
Ответ на: комментарий от kostyarin_

В мане пишут, что

In addition, the variant programs egrep and fgrep are the same as grep -E and grep -F, respectively. These variants are deprecated, but are provided for backward compatibility.

smalcom
() автор топика
Ответ на: комментарий от smalcom

Так просто же вроде, поиск первого и второго соответственно:

$ cat qq | egrep '^[^+]*\+[^+]*$'
$ cat qq | egrep '^[^+]*\+[^+]*\+[^+]*$'

третье по аналогии.

А поделку на божественном Расте еще не советовали? )

pavlick ★★
()
Последнее исправление: pavlick (всего исправлений: 1)
Ответ на: комментарий от pavlick

Заработало, спасибо.

А я остановился на варианте типа '([^+]*\+){2}' и не мог понять, что не так. Неправильно понял действие оператора повторения {n}.

А поделку на божественном Расте еще не советовали? )

Поскольку она недавно была в новостях, то я и про неё вспомнил. Но по демонстрации мне показалось, что она мне просто даст варианты разделённые «|» и всё. А у меня в уравнениях могут быть аргументы разные: и C, и D и вложенные выражения.

Всем спасибо.

smalcom
() автор топика
Последнее исправление: smalcom (всего исправлений: 1)
Ответ на: комментарий от smalcom

Таки добил мысль с повторениями)

[smalcom@smalcom release]$ cat test 
1. A0 = A1 + A2
2. A0 = (A1 + A2) * (A3 + A4)
3. A0 = (A1 + A2) + (A3 + A4)
4. A0 = (A1 + A2) + (A3 + A4) * (A1 + A2) * (A3 + A4)
[smalcom@smalcom release]$ 
[smalcom@smalcom release]$ grep -E '^([^+]*\+[^+]*){1}$' test
1. A0 = A1 + A2
[smalcom@smalcom release]$ grep -E '^([^+]*\+[^+]*){2}$' test
2. A0 = (A1 + A2) * (A3 + A4)
[smalcom@smalcom release]$ grep -E '^([^+]*\+[^+]*){3}$' test
3. A0 = (A1 + A2) + (A3 + A4)
[smalcom@smalcom release]$ grep -E '^([^+]*\+[^+]*){4}$' test
[smalcom@smalcom release]$ grep -E '^([^+]*\+[^+]*){5}$' test
4. A0 = (A1 + A2) + (A3 + A4) * (A1 + A2) * (A3 + A4)
smalcom
() автор топика
Ответ на: комментарий от smalcom
int main(int argc, char * * argv) {
  char buf[1000], *p;
  unsigned int n, j;
  n = atoi(argv[1]);
  while(fgets(buf, sizeof(buf), stdin)) {
    for(j=0,p=buf; j<=n && (p=strchr(p,'+')); j++,p++);
    if(j==n) fputs(buf, stdout);
  }
}

разумеется, для продакшн-качества надо избавиться от фиксированной максимальной длины строки (1000) и проверять что argv[1] это действительно число а не мусор, и проверять чтобы j не переполнилось, если n==(unsigned)-1 и мы нашли больше совпадений, ну и добавить поддержку строк в файле, которые не влезают в память (например строка длиной 10ГБ на 32-бит платформе; подозреваю grep такое тоже не поддерживает)

firkax ★★★★★
()
Последнее исправление: firkax (всего исправлений: 2)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.