Скрипт sed для печати строк между последним вхождением шаблона и пустой строкой

Это была проблема среды pip. Я действительно не понимаю этого, потому что я уверен, что шаги, которые решили это, не сработали в первые пару раз, когда я их пробовал... Но выполняя sudo apt-get remove awscli, затем pip3 uninstall awscliкак оба пользователя, затем sudo pip3 install awscli, наконец, установили это как я надеялся.

После прочтения десятков вопросов и ответов о pip все, что я знаю, это то, что я не понимаю, как различные версии pip взаимодействуют с --разрешениями пользователя и sudo. Я не собираюсь отмечать свой ответ как правильный, но с удовольствием рассмотрю любые другие ответы.

0
30.04.2021, 04:15
3 ответа

Используя потоковый редактор sed, мы обнаруживаем запись шаблона и с этого момента пропускаем строку и повторяемся до тех пор, пока не будет найдена следующая пустая строка. До этого времени накапливайте записи в пространстве шаблонов и после зацикливания перезаписывайте содержимое пространства хранения содержимым пространства шаблонов. Это происходит заново для каждого шаблона... пустой блок строк. В конце файла извлеките содержимое удержания и распечатайте его, если оно не пусто.

$ sed -ne '
  /pattern/{
    $d;n
    :loop
      s/\n$//;tdone
      $bdone;N
    bloop
    :done
    x
  }
  ${x;/./p;}
' file
6
7
8
9

Больше всего. естественным подходом для такого диапазона задач является линейный редактор ed

ed -s file <<\eof
a

.
?pattern?+1;/^$/-1p
Q
eof

Еще один способ использования редактора sed GNU — это сбор фрагментов в области хранения с помощью оператора диапазона.

sed -e '
  /pattern/,/^$/!ba
  /./!ba
  H;/pattern/{z;x;}
  :a
  $!d;x;s/.//
' file

Мы можем использовать редактор GNU sed в режиме slurp и использовать жадность регулярных выражений для достижения последнего экземпляра шаблона

sed -Ez '
  s/.*pattern\n(([^\n]+\n)+)(\n.*)?/\1/
' file

Ниже приведен sed-эквивалент оператора диапазона в perl. Массив @A функционирует как область охвата блок-линий.

perl -ne 'next unless
  my $e = /pattern/.. /^$/;
  @A = $e == 1 ? ()
     :   /./   ? (@A, $_)
     :            @A;
  }{print @A;
' file
4
28.07.2021, 11:36

Мне кажется, что предыдущее решение может быть расширено для решения этой проблемы:

printf '%s\n' '?pattern?+1' '. +1,/^$/ -1 p' | ed -s file

Это отправляет две команды наed:

  • ?pattern?+1--поиск образца назад от конца файла, затем переход на одну строку вперед от этого совпадения; это печатает эту строку
  • . +1,/^$/ -1 p--со следующей строки (текущая плюс 1 )через строку перед следующей пустой строкой (/^$/ -1), напечатать эти строки

Это не удастся, если между patternи следующей пустой строкой нет двух строк, если patternнет в файле или если после patternнет пустой строки.

1
28.07.2021, 11:36
awk '/pattern/,/^$/ { arr[NR]=$0; if (/pattern/) line1=NR; if (/^$/) line2=NR}END{ if (line1) for(i=++line1;i<line2;i++) print arr[i]}' file

/pattern/,/^$/получит строки между шаблоном и пустой строкой.

Затем if (/pattern/) line1=NRвыдает номер записи последней строки, в которой найден шаблон. if (/^$/) line2=NRдает номер последней пустой строки после того, как шаблон найден .

Наконец цикл for между двумя записями возвращает ожидаемый результат.

Это не удастся, если между шаблоном и следующей пустой строкой нет двух строк, если шаблона нет в файле или если за шаблоном нет пустой строки. (Взято из здесь)

2
28.07.2021, 11:36

Теги

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