У меня есть файл testfile.txt содержащий

pippo=x
pluto=y
1234=z

Я хотел бы удалить только первую строку, соответствующую /^[a-z]\+=/ (первая строка в этом примере).

Я пытался с помощью следующей команды, но безуспешно:

sed   '/^[a-z]\+=/,+0d' testfile.txt

но первые две строки удалены.

Есть ли способ сделать это с помощью sed?

С уважением

2 ответа2

1

@ John1024 Извините, но ваше решение работает только в том случае, если первая совпадающая строка является первой строкой файла.

Я решил проблему с помощью следующего кода sed -r '0,/^[a-z]\+=/{//d;}' testfile.txt но я все еще убежден, что мое предыдущее решение должно было работать даже с posix sed ,

Фактически идея заключалась в том, чтобы задать в качестве адреса второй строки смещение в 0 строк ... но он все равно удаляет также следующую строку, это звучит как ошибка.

от man sed в убунту 14.04

... addr1,+N Будет соответствовать addr1 и N строкам, следующим за addr1. ...

1

Проблема с вашей командой sed

$ sed '/^[a-z]\+=/,+0d' testfile.txt

является то, что сценарий sed применяется к каждой строке входных данных.

+0 (который является расширением GNU) означает, что ваш скрипт эквивалентен

$ sed '/^[a-z]\+=/d' testfile.txt

и первая и вторая строки будут удалены, как вы заметили.

Кстати, вы получите точно такой же эффект, используя +1 , но по другим причинам. Команда d вместо того, чтобы применяться к первой и второй строкам по отдельности, будет применена к первым двум строкам из-за совпадения в первой строке (то есть диапазон команды d будет равен строкам одна и еще одна, +1), Это не удаляет третью строку, потому что это вне диапазона.

GNU sed решение

$ sed '0,/^[a-z]\+=/{//d}' testfile.txt

этот пользователь @Whitefield опубликовал работу и он довольно хорош (хотя опция -r не нужна, и начальный адрес 0 может быть изменен на 1 в этом случае, если вы хотите использовать больше POSIX-ish).

Вариант BSD sed того же подхода будет выглядеть

$ sed '1,/^[a-z]+=/{/^[a-z]+=/d
  }' testfile.txt

Экранирование + необходимо только в том случае, если ваш sed реализует "устаревшие базовые регулярные выражения", а не "современные базовые регулярные выражения". Как BSD sed и GNU sed в моей системе (Mac OS X) выглядят как "современные". POSIX не имеет этого различия, и чтение руководств (re_format(7) для BSD, которое делает это различие) и спецификация POSIX бок о бок заставляют меня вертеть головой.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .