Команда для вывода каждой строки вперед, а затем назад

Ваша ошибка в том, что вы создали две отдельные файловые системы BTRFS. Вы можете увидеть в выводе sudo btrfs fiдве файловые системы, каждая с одним устройством.

Чтобы исправить это, используйте команду btrfs device add, чтобы добавить новый диск в существующую файловую систему. ТОГДА сделайте ребаланс.

https://btrfs.wiki.kernel.org/index.php/Manpage/btrfs-device

6
14.09.2019, 23:18
5 ответов

В большинстве случаев будет много проблем из-за того, как работает буферизация stdio. Обходной путь для Linux может состоять в том, чтобы использовать программу stdbufи запустить команду с помощью coproc, чтобы вы могли явно управлять чередованием вывода.

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

#!/bin/bash
coproc stdbuf -i0 -o0 "$@"
IFS=
while read -r in ; do
    printf "%s " "$in"
    printf "%s\n" "$in" >&${COPROC[1]}
    read -r out <&${COPROC[0]}
    printf "%s\n" "$out"
done

Если требуется более общее решение, так как OP требует только каждой строки ввода в программу, чтобы в конечном итоге вывести одну строку, а не немедленно, тогда необходим более сложный подход. Создайте цикл событий, используя read -t 0, чтобы попытаться прочитать из стандартного ввода и процесса co -, если у вас есть один и тот же «номер строки» для обоих, затем выведите, в противном случае сохраните строку. Чтобы избежать использования 100% процессора, если в любом раунде цикла событий ни один из них не был готов, введите небольшую задержку перед повторным запуском цикла событий. Существуют дополнительные сложности, если процесс выводит неполные строки, их необходимо буферизовать.

Если необходимо это более общее решение, я бы написал его, используя expect , так как оно уже имеет хорошую поддержку обработки сопоставления шаблонов для нескольких входных потоков. Однако это не решение для bash/zsh.

6
27.01.2020, 20:21

Функция оболочки. Это будет работать в любой оболочке, которая поддерживает строки <<<здесь -, включая zsh и bash.

xyz() { 
    while read line
    do 
        printf "%s " "$line"
        "$@" <<<"$line"
    done
}

$ (echo "foo"; echo "bar") | xyz rev
foo oof
bar rab
6
27.01.2020, 20:21

В данном конкретном случае я бы использовалperl:

printf '%s\n' foo bar | perl -Mopen=locale -lpe '$_.= " ". reverse$_'
foo oof
bar rab

Который вы можете расширить для работы с графемными кластерами:

$ printf '%s\n' $'complique\u301' |
    perl -Mopen=locale -lpe '$_.= " ". join "", reverse/\X/g'
compliqué éuqilpmoc

илиzsh:

while IFS= read -r line; do
  print -r -- $line ${(j::)${(s::Oa)line}}
done

Хотя я бы не стал использовать while readциклы для обработки текста , даже вzsh(даже если в данном конкретном случае это не так уж плохо, поскольку используются только встроенные команды ).

В общем случае использование временных файлов, вероятно, является лучшим подходом. С zsh,вы можете сделать это с помощью:

(){paste -d ' ' $1 <(rev <$1)} =(print -l foo bar)

(, где =(...)создает и очищает временный файл ).

Замена его конвейерами и некоторой формой teeing — это рецепт тупиковой ситуации в общем случае. См. эти похожие вопросы для некоторых подходов и подробностей о тупиковых ситуациях:

3
27.01.2020, 20:21

Это gawkреализация со -процессного подхода , описанного icarus и, следовательно, с учетом тех же соображений буферизации stdio, см. также это

{ echo foo; echo bar; } |  gawk -vcmd=rev '
 BEGIN {c=sprintf("stdbuf -i0 -o0 \"%s\"", cmd)}
 {
  printf "%s ", $0
  print |& c; fflush()
  c |& getline
  print
 }'

foo oof
bar rab
2
27.01.2020, 20:21

Именованные каналы спешат на помощь!

xyz() {
  pipe="/tmp/$$pipe"
  mkfifo "$pipe"
  tee "$pipe" | "$@" | paste "$pipe" -
  rm "$pipe"
}

Результаты вашего примера команды:

$ (echo "foo"; echo "bar") | xyz rev
foo oof
bar rab

Приведенная выше функция делает именно то, что вы описываете.

1
27.01.2020, 20:21

Теги

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