Предположим, что сценарий, генерирующий выходные данные, называется generate
. Затем, чтобы отобразить количество секунд, необходимое для создания каждой строки:
$ generate | ( t0=$(date +%s); while read -r line; do t1=$(date +%s); echo " $((t1-t0)) $line"; t0=$t1; done )
2 foo
0 foo
5 foo
3 foo
Одни и те же команды, разбросанные по нескольким строкам, выглядят так:
generate | ( t0=$(date +%s)
while read -r line
do
t1=$(date +%s)
echo " $((t1-t0)) $line"
t0=$t1
done
)
В качестве альтернативы, для удобства, мы можем определить функцию оболочки, содержащую этот код:
timer() { t0=$(date +%s); while read -r line; do t1=$(date +%s); echo " $((t1-t0)) $line"; t0=$t1; done; }
Мы можем использовать эту функцию следующим образом:
$ generate | timer
0 foo
2 foo
4 foo
3 foo
t0=$(date +%s)
Это фиксирует текущее время в начале сценария в секундах -с эпохи -.
while read -r line; do
Это запускает цикл, который читает со стандартного ввода
t1=$(date +%s)
Это фиксирует время в секундах -с -эпохи, в которую была захвачена текущая строка.
echo " $((t1-t0)) $line"
Выводит время в секундах, которое потребовалось для текущей строки.
t0=$t1
Это обновляет t0
для следующей строки.
done
Это сигнализирует об окончании цикла while
.
Из-за конвейера стандартный ввод перенаправляется на цикл while
; который включает в себя любую команду, запущенную из него, например vim
.
Поскольку вы всегда хотите получать ввод с терминала, вы можете просто повторно -подключиться к терминалу,/dev/tty
:
< /dev/tty vim -o "$student"
В качестве альтернативы, stdin может быть сохранен в файловом дескрипторе до перехода в конвейер(exec 6<&0
)и передан Vim(<&6 vim -o...
). (Это также подходит для случая, когда «запись макросов» команд Vim сохраняется в файле, и вы хотите автоматизировать сам Vim, возвращая записанные входные данные обратно в него.)
Или вы можете попытаться полностью избавиться от конвейера, сначала прочитав все содержимое файла в массив Bash (readarray
), а затем используя простой for
цикл. Это потребовало бы больше памяти, но здесь это не должно быть проблемой, так как ограничивающим фактором является количество сеансов Vim, которые вы готовы обрабатывать последовательно :-). На самом деле, здесь вы читаете не из файла, ано из содержимого переменных (, которые, как я понимаю, имеют пробел -разделенных студентов на потенциально несколько строк -синтаксический анализ по умолчанию IFS
разделит их на отдельных студентов ), поэтому все, что вам нужно сделать, это просто разбиение слов на массив Bash:
declare -a students=($student_files)
for student in "${students[@]}"
do
vim -o "$student"
done
или полный пропуск промежуточного массива:
for student in $student_files
do
vim -o "$student"
done
]# cat filelist
fsc
out
]# vim -o $(<filelist)
2 files to edit
]#
...и между ними у меня были эти два файла "fsc" и "out" , сложенные в vim.
Однажды я использовал man vim
.
Мне пришлось отказаться от моего окна xterm после того, как я протестировал ваш скрипт. Даже после reset
клавиша BS будет выполнять только "^H". Так я радикально изменился.
declare -a student_array=()
while read line ; do student_array+=("$line") ; done < <(echo -e "$student_array")
for student in "${student_array[@]}" ; do
vim -o $student
done