Есть ли способ прочитать строки из вывода команды?

8

У меня есть предварительная команда процесса для вывода файла

./preprocess.sh > preprocessed_file 

и preprocessed_fileбудет использоваться как это

while read line
do

    ./research.sh $line &

done < preprocessed_file 

rm -f preprocessed_file

Есть ли способ направить вывод на while read lineчасть вместо вывода в preprocessed_file? Я думаю, что должен быть лучший способ, чем использовать этот темп preprocessed_file.

Маркус Торнтон
источник

Ответы:

8

Вы можете использовать замену процесса bash :

while IFS= read -r line; do
  ./research.sh "$line" &
done < <(./preprocess.sh)

Некоторые преимущества процесса замещения:

  • Нет необходимости сохранять временные файлы.
  • Лучшая производительность. Чтение из другого процесса часто быстрее записи на диск, затем повторное чтение.
  • Экономьте время на вычислениях, поскольку, когда они выполняются одновременно с расширением параметров и переменных, подстановкой команд и арифметическим расширением
cuonglm
источник
что означают двойные стрелки влево (<<)?
Маркус Торнтон
@MarcusThornton: <перенаправление, а <(...)синтаксис замещения процесса. Вы должны прочитать: gnu.org/software/bash/manual/html_node/… для получения более подробной информации.
cuonglm
Понял. <(...)является частью синтаксиса.
Маркус Торнтон
2
Это не обязательно быстрее. Потому что при чтении из канала readнеобходимо читать по одному байту за раз, при этом он может оптимизировать вещи с помощью чтения больших кусков и искать назад при чтении из обычного файла. Лучше while readвсего вообще избегать петель, когда это возможно. Также обратите внимание, что вам нужно IFS= read -r lineпрочитать строку в $line. И оставлять без $lineкавычек (вызывая оператор split + glob) здесь, вероятно, не имеет смысла.
Стефан Шазелас
1
@mikeserv, команды часто строки-буфер (как противостоять полному буферу) их выход , когда он идет к терминалу. Здесь я говорю, что readвстроенная оболочка читает по одному символу за раз при чтении из канала (независимо от того, что находится на другом конце канала, который readне имеет возможности узнать), что является одной из причин, по которой while readциклы чрезвычайно медленные.
Стефан Шазелас
15

Да! Вы можете использовать технологическую трубу |.

./preprocess.sh |
    while IFS= read -r line
    do
        ./research.sh "$line" &
    done

Канал процесса передает стандартный вывод ( stdout) одного процесса в стандартный ввод ( stdin) следующего.

При желании вы можете поставить символ новой строки после a |и расширить команду до следующей строки.

Примечание: a|bэквивалентно b < <(a), но без волшебных файлов и в более читаемом порядке, особенно когда конвейер становится длиннее.

a|b|c эквивалентно c < <(b < <(a))

а также

a|b|c|d|e является e < < (d < <(c < <(b < <(a))))

Ctrl-Alt-Делор
источник
3
Примечание. Преимущество этого решения с конвейером заключается в том, что он более переносим, ​​чем подстановка процессов (не поддерживается некоторыми оболочками POSIX, такими как dash). Что касается переносимости, правая часть канала может быть выполнена в подоболочке (это зависит от оболочки), так что любой побочный эффект (например, установка переменных) может не влиять на среду сценария оболочки.
vinc17
Как правило, безопаснее помещать ссылки $lineна переменные, например, в двойные кавычки (например, в вашем скрипте ./research.sh "$line" &).
G-Man говорит: «Восстановите Монику»
1
@ G-Man Возможно, не в этом контексте. Если research.shработает с массивом аргументов командной строки и $line, например, «один два» с намерением, чтобы первый аргумент был «один», а второй аргумент «два», цитирование $lineсделает это невозможным - вместо этого первый аргумент будет "один два", и второго не будет ...
Златовласка
2
« a|bэквивалентноb < <(a) » - близко, но не совсем. В версии канала обе стороны канала выполняются в подоболочках, в то время как в версии подстановки процессов в подоболочке запускается только замещенный процесс, но aвыполняется в объеме текущего выполняемого уровня оболочки. Это имеет важные последствия для объема переменных, установленных внутриa
Digital Trauma