Как открыть vim внутри скрипта bash?

Предположим, что сценарий, генерирующий выходные данные, называется 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.

0
06.11.2019, 16:35
3 ответа

Из-за конвейера стандартный ввод перенаправляется на цикл 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
5
28.01.2020, 02:22
]# cat filelist 
fsc
out
]# vim -o $(<filelist)
2 files to edit
]# 

...и между ними у меня были эти два файла "fsc" и "out" , сложенные в vim.

Однажды я использовал man vim.

Мне пришлось отказаться от моего окна xterm после того, как я протестировал ваш скрипт. Даже после resetклавиша BS будет выполнять только "^H". Так я радикально изменился.

0
28.01.2020, 02:22
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
0
28.01.2020, 02:22

Теги

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