Отрицаем часть рисунка с помощью sed - PullRequest
1 голос
/ 16 мая 2019

Я хочу создать шаблон, который найдет первую строку, которая соответствует шаблону, и заменит ее:

sed -r '0,/^[a-z0-9]* (ALL=\(ALL\) ALL)/s//abc \1\n&/'

Мой ввод - файл /etc/sudoers.

Я бы хотел изменить ^[a-z0-9]* на что-то вроде /^ALL/!, но у меня это не работает.

Ответы [ 3 ]

1 голос
/ 18 мая 2019

Замена первого вхождения в файле

Если я понимаю ваш вопрос и вы хотите найти первую строку в файле, которая соответствует ^[a-z0-9]+ ALL=(ALL) ALL, и заменить ^[a-z0-9]+ ALL на что-то вроде^ABC используя Расширенное регулярное выражение , вы можете использовать:

sed -r '0,/[a-z0-9]+/s/^[a-z0-9]+ ALL(=\(ALL\) ALL.*$)/^ABC\1/'

Просмотр некомментированных строк в /etc/sudoers с доступом sudo, предоставленным членам группы wheel, вы должны иметь:

$ noc /etc/sudoers
root ALL=(ALL) ALL
%wheel ALL=(ALL) ALL
%wheel ALL=(ALL) NOPASSWD: ALL

Таким образом, чтобы заменить первую строку на [a-z0-9]+ ALL=(ALL) ALL в /etc/sudoers на ^ABC=(ALL) ALL, вы должны:

$ noc /etc/sudoers | sed -r '0,/[a-z0-9]+/s/^[a-z0-9]+ ALL(=\(ALL\) ALL.*$)/^ABC\1/'
^ABC=(ALL) ALL
%wheel ALL=(ALL) ALL
%wheel ALL=(ALL) NOPASSWD: ALL

Редактировать в-Комментарий

В своем комментарии вы говорите, что хотите найти "<string> ALL=(ALL) ALL, где string может быть всем, но не 'ALL'".Так как sed не поддерживает просмотр вперед или назад, лучшее, что вы можете сделать, это явно не соответствовать ALL в начале строки.Это означает, что вы хотите найти строки, начинающиеся ^[^A][^L][^L].Хотя это несколько ограничительно, он будет искать строку, которая не начинается с "ALL", но это может быть вашим единственным выходом.Например:

sed -r '0,/^[^A][^L][^L]/s/^[^A][^L][^L][^ ]+( ALL=\(ALL\) ALL.*$)/^ABC\1/'

Снова возьмите пример файла sudoers и включите ALL ALL=(ALL) ALL, который вы не хотите сопоставлять, например,

$ cat sudoers
ALL ALL=(ALL) ALL
root ALL=(ALL) ALL
%wheel ALL=(ALL) ALL
%wheel ALL=(ALL) NOPASSWD: ALL

Теперь примените выражение, определяющее первый <string> не ALL в <string> ALL=(ALL) ALL и вы получите:

$ sed -r '0,/^[^A][^L][^L]/s/^[^A][^L][^L][^ ]+( ALL=\(ALL\) ALL.*$)/^ABC\1/' sudoers
ALL ALL=(ALL) ALL
^ABC ALL=(ALL) ALL
%wheel ALL=(ALL) ALL
%wheel ALL=(ALL) NOPASSWD: ALL

Заменить пронумерованное вхождение в строке

Если вы хотите заменить вхождениев пределах линии.С расширенным регулярным выражением, используя s/find/replace/n, где n=1,2,3.. - это вхождение шаблона find для замены, вы можете заменить первое вхождение, например,

sed -r 's/[0-9a-z]+/cde456/1'

Например:

$ echo "abc123---abc123---abc123" | sed -r 's/[0-9a-z]+/cde456/1'
cde456---abc123---abc123

Или для замены второго вхождения вы должны использовать:

$ echo "abc123---abc123---abc123" | sed -r 's/[0-9a-z]+/cde456/2'
abc123---cde456---abc123

Такое же сопоставление вхождений доступно для базовых регулярных выражений, у вас просто нет '+' (соответствует одному или нескольким вхождениям), необходимо ли изменить шаблон find, например

sed 's/[0-9a-z][0-9a-z]*/cde456/1`

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

1 голос
/ 18 мая 2019

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

([^abc]*)(.*)

enter image description here

#!/bin/bash
STRING="(ALL=(ALL) ALL)/s//abc"
MATCH="$(sed 's/\([^abc]*\)\(.*\)/\1/' <<< $STRING)"
echo $MATCH

Выходные данные

(ALL=(ALL) ALL)/s//

RegEx

Если это не ваше желаемое выражение, вы можете изменить / изменить его выражения в regex101.com .

RegEx Circuit

Вы также можете визуализировать свои выражения в jex.im :

enter image description here

0 голосов
/ 06 июня 2019

Я понимаю, что вы хотите избежать совпадения с первым вхождением шаблона, если ALL присутствует в детали перед подстрокой ALL=(ALL) ALL.

Используйте

sed -i '/^.*ALL.* ALL=(ALL) ALL/b;s/^.* \(ALL=(ALL) ALL\)/abc \1\n&/;T;:a;n;ba' file

Если у вас нет GNU sed, вы можете попробовать

sed -i '' -e '/^.*ALL.* ALL=(ALL) ALL/b' -e 's/^.* \(ALL=(ALL) ALL\)/abc \1\n&/' -e ':a;n;ba' file

ПРИМЕЧАНИЯ

  • /^.*ALL.* ALL=(ALL) ALL/b; - находит строку с ALL до ALL=(ALL) ALL и останавливает обработку этой строки
  • s/^.* \(ALL=(ALL) ALL\)/abc \1\n&/ выполняет замену (примечание .* будет соответствовать любым 0 или более символам как можно больше)
  • T - если не удалось, завершите обработку этой строки
  • :a;n;ba - цикл, который заставляет sed просто читать и печатать оставшиеся строки до конца файла.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...