Linux -Поиск всех вхождений определенного шаблона в строке файла

Самый простой способ отсеять дубликаты, не прибегая к пробам -и -ошибкам, — посмотреть на вывод apt policy. Для каждого доступного репозитория (, пакета и архитектуры ), apt policyбудет отображаться дескриптор репозитория; вы должны попытаться закончить только с одним из каждого.

Например, с репозиториями, которые вы указали в своем вопросе, apt policyпокажет что-то вроде

 500 http://ftp.am.debian.org/debian buster/main amd64 Packages
     release v=10.0,o=Debian,a=stable,n=buster,l=Debian,c=main,b=amd64
     origin ftp.am.debian.org
 500 http://ftp.au.debian.org/debian buster/main amd64 Packages
     release v=10.0,o=Debian,a=stable,n=buster,l=Debian,c=main,b=amd64
     origin ftp.au.debian.org
 500 http://ftp.am.debian.org/debian buster/contrib amd64 Packages
     release v=10.0,o=Debian,a=stable,n=buster,l=Debian,c=contrib,b=amd64
     origin ftp.am.debian.org
 500 http://ftp.au.debian.org/debian buster/contrib amd64 Packages
     release v=10.0,o=Debian,a=stable,n=buster,l=Debian,c=contrib,b=amd64
     origin ftp.au.debian.org

Вторая строка каждой записи должна быть продублирована -; в пример выше

     release v=10.0,o=Debian,a=stable,n=buster,l=Debian,c=main,b=amd64

и

     release v=10.0,o=Debian,a=stable,n=buster,l=Debian,c=contrib,b=amd64

Самый простой вариант при выборе того, какую запись сохранить, — это иметь одну deb.debian.orgзапись (, которая будет использовать перенаправление, чтобы каждый раз давать вам закрытое зеркало ).

-1
01.10.2021, 05:18
3 ответа

Использование Raku (, ранее известного как Perl _6)

raku -ne 'put $/.join("\n") if m:g/\(memberOf\=CN\= <(.*?)> \)/;'

ИЛИ

raku -ne 'put $/.join("\n") if m:g/<?after \(memberOf\=CN\= > (.*?) <?before \) > /;'

Вкратце, в примере 1 используются разделители совпадений <(…)>в Raku, которые предписывают обработчику регулярных выражений отбрасывать все совпадения за пределами <(.*?)>. Пример 2 использует <?after "pattern1" >положительный просмотр назад и <?before "pattern2" >положительный просмотр вперед, чтобы изолировать все -между ними. Если важна нечувствительность к регистру -, просто изменитеm:g('совпадение -глобальное' )наm:g:i('соответствие -глобальное регистро-нечувствительное' ).

Ввод образца:

(memberOf=CN=Group1)(memberOf=CN=Group2)(memberOf=CN=Group3)(memberOf=CN=Group4)

Пример вывода (1):

Group1
Group2
Group3
Group4

ИЛИ Образец вывода (2):

Group1 Group2 Group3 Group4

Представьте себе на секунду, что OP имеет файл с несколькими строками, похожими на показанную в примере строку, тогда может иметь смысл возвращать все выходные данные в одну строку. Для любого из приведенных выше примеров простое изменение $/.join("\n")на $/приводит к тому, что каждый построчный захват возвращает построчный (вывод 2 выше ).

Наконец, OP может иметь позиционную информацию, закодированную в списке «Группа» (, например. нижняя группа #s слева, высшая справа ). В этом случае имеет смысл выделитьcomb()-совпадения и отобразить их как .pairs, как показано ниже:

raku -ne '.raku.say for.comb(/<?after \(memberOf\=CN\= > (.*?) <?before \) > /).pairs;' 

0 => "Group1"
1 => "Group2"
2 => "Group3"
3 => "Group4"

https://docs.raku.org/language/regexes
https://raku.org

0
01.10.2021, 07:40

Много способов сделать это, вот решение, использующее широко доступные функции grepс упором на удобочитаемость для человека.

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

echo "(memberOf=CN=Group1)(memberOf=CN=Group2)(memberOf=CN=Group3)(memberOf=CN=Group4)" \
  | grep -Eo "[(]memberOf=CN=[^)]+" \
  | grep -Eo "[^=]+$"

Это работает в два этапа.

Сначала извлекаем все паттерны (memberOf=CN=somethingбез замыкания )— это важно для нашего второго этапа. Они выходят по очереди «бесплатно», что облегчает нашу работу на втором этапе. Любые строки во входных данных, которые не соответствуют этому шаблону, будут проигнорированы, поэтому он также должен работать там, где среди прочего скрыты требуемые строки.

Затем мы сопоставляем все, что не =, начиная с конца строки и двигаясь в обратном порядке. Это приводит к удалению части memberOf=CN=строки.

Если регистр ввода не может быть гарантирован, добавьте iк флагам первого grep.

Одно предостережение :Если в ваших значениях CNесть экранированные )или =, это не будет работать должным образом.

0
01.10.2021, 08:15

Это решение чем-то похоже на решение @bxm, но с шагом sedвместо чисто grep.

grep -Eo '\(memberOf=CN=[^()]*\)' |
sed 's/(memberOf=CN=\(.*\))/\1/' 

Вход:

(memberOf=CN=Group1)(memberOf=CN=Group2)(memberOf=CN=Group3)(memberOf=CN=Group4)
(memberOf=CN=GroupA1)
(memberOf=CN=GroupA2)(memberOf=CN=GroupA3)
(memberOf=CN=GroupA4)
(rememberOf=CN=GroupX1)(memberOf=CN=GroupX2)
(numberOf=CN=GroupX4)
(memberOf=CN=GroupB1)(memberOf=CN=GroupB2)(memberOf=CN=GroupB3)(memberOf=CN=GroupB4)

Выход:

Group1
Group2
Group3
Group4
GroupA1
GroupA2
GroupA3
GroupA4
GroupX2
GroupB1
GroupB2
GroupB3
GroupB4

Выход из grepпоявляется на входе sedкак:

(memberOf=CN=Group1)
(memberOf=CN=Group2)
(memberOf=CN=Group3)
(memberOf=CN=Group4)
...
Затем

sedберет этот вывод и удаляет начальный (memberOf=CN=и замыкающий ).

Этот код можно сделать немного более общим, добавив подстановочные знаки в большей части строки sed:

grep -Eo '\(memberOf=CN=[^()]*\)' |
sed 's/.*=\(.*\))/\1/'
0
02.10.2021, 00:00

Теги

Похожие вопросы