1

Пример файла:

abc
def
%separator
eee
fff
%separator
xxx
yyy
zzz

Можно ли разбить этот файл на логические части, а именно:

часть 1:

abc
def

часть 2:

eee
fff

часть 3:

xxx
yyy
zzz

затем вызвать какую-либо команду (скажем, wc -l) для каждой из этих частей без создания временных файлов? Я ищу что-то вроде xargs , которое не будет вставлять аргументы, а вместо этого проталкивает их через стандартный ввод.

1 ответ1

1

Я не знаю такого инструмента. Я придумал следующий сценарий. Настройте его под свои нужды:

#!/bin/bash

sprtr='%separator'
cmmnd='wc -l'

set -o pipefail

while ! sed -n "/^${sprtr}$/q1;p" | $cmmnd ; do
 :
done

Это выглядит так:

  1. sed читает из stdin пока не найдет данный разделитель или EOF, затем завершит работу.
  2. Выбранная команда получает соответствующий фрагмент из sed .
  3. Если $cmmnd не завершится с ошибкой, set -o pipefail ! и q1 сотрудничают, поэтому, когда $sprtr найден, весь канал возвращает состояние выхода 0 . Это выполняет (пустой) код между do и done , затем зацикливается, поэтому sed запускается снова для обслуживания следующего фрагмента.
  4. Если $cmmnd завершается с ошибкой или если $sprtr не найден (EOF достигнуто), весь канал возвращает ненулевой статус выхода. Это делает сценарий оставить while цикла.

Некоторые подводные камни:

  • Вы не можете использовать любой разделитель буквально и бездумно. Некоторые значения $sprtr нарушают команду sed или изменяют ее поведение, если вы не экранируете символы, специально предназначенные для ее синтаксиса. Примеры: / , /q; / .
  • set -o pipefail работает в Bash 3 и выше, я думаю. Альтернатива (но не совсем эквивалентная) - mispipe от moreutils .
  • Ваш sed должен понимать q1 (это завершает sed с кодом выхода 1).

Я признаю, что в этом решении не так много элегантности.

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