оболочка: добавление в выходные данные пробелов с помощью вставки

#shell

#оболочка

Вопрос:

Требуется много времени, чтобы добавить 4 пробела к некоторым выводам оболочки и преобразовать их в действительный код markdown. Например. При публикации вопроса или ответа здесь, в stackoverflow.

На самом деле это довольно легко сделать с sed :

 some_command | sed -e 's/^/    /'
  

Но я бы хотел сделать это с paste , если возможно. Поскольку paste в качестве входных данных используется 2 файла, все, что я придумал, это:

 some_command | paste 4_space_file -
  

где 4_space_file на самом деле это файл, все содержимое которого состояло из 4 пробелов.

Есть ли более аккуратный способ добиться этого с paste без фактического файла на жестком диске?

Комментарии:

1. Что вы делаете, если ваша 4_space_file длина отличается от длины вывода из some_command ? Кроме того, что вы делаете с символом табуляции, который paste вставляется? (То есть: Я подвергаю сомнению предположение, встроенное в этот вопрос, что paste является подходящим инструментом для текущей работы).

Ответ №1:

Буквальные ответы с использованием вставки

Во-первых, чтобы ответить на ваш буквальный вопрос:

 some_command | paste <(printf '    n') -
  

…выдает тот же результат, что и передача paste имени файла с одной строкой, содержащей четыре пробела и новую строку в качестве содержимого. Однако вывод из paste в этом случае представляет собой не четырехсимвольные отступы для каждой строки; первая строка содержит четыре пробела и табуляцию, перед последующими строками ставится только табуляция.

Если бы вы хотели сгенерировать входные данные соответствующей длины, продолжая использовать paste , то в итоге получили бы что-то более уродливое. Скажем (с bash 4.0 или новее):

 ls | {
   mapfile -t lines                              # read output from ls into an array

   # our answer, here, is to move to three spaces in the input, and use paste -d' ' to
   # ...add a fourth space during processing.
   paste -d' ' 
       <(yes '   ' | head -n "${#lines[@]}") 
       <(printf '%sn' "${lines[@]}")
}
  

<() это синтаксис подстановки процесса, который расширяется до имени файла, которое при чтении из которого выдает вывод из содержащегося кода.


Лучшие ответы

Для собственного подхода bash вы также можете рассмотреть возможность определения функции:

 ident4() { while IFS= read -r line; do printf '    %sn' "$line"; done; }
  

…для последующего использования:

 some_command | indent4
  

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


Также рассмотрите awk :

 awk '{ print "    " $0; }'