Завершить сценарий Bash в зависимости от конвейерного вывода

Я написал следующий сценарий оболочки:

#!/bin/bash


counter=0

while [ $counter -lt 250 ]; do
        perl Cumulative_Percentage.pl TP53.lst T1_endo.maf >> OutFile
        perl Optimize_Panel.pl TP53.LST T1_endo.maf >> TP53.lst 
        let counter=counter+1
done

И это работает хорошо. Проблема в том, что он часто выполняет гораздо больше циклов, чем нужно. Perl-скрипт Optimize_Panel.pl печатает одну строку, если цикл должен продолжаться, или завершает работу без печати, если цикл должен остановиться. Я хочу, чтобы цикл while завершался, если Optimize_Panel.pl закрывается вместо печати... но как?

Одно из возможных решений, которое я могу себе представить, - запустить

wc TP53.lst

в начале и конце цикла; сначала установив его в переменную, затем проверив, увеличилось ли оно, а затем приведя его к преждевременному оператору done, если TP53.lst не был добавлен. Я уверен, что это может сработать, но это кажется неуклюжим, и я подозреваю, что есть гораздо более простой способ изменить сценарий оболочки.

Другой способ, который я могу придумать, - это передать вывод Optimize_Panel.pl во временный файл, а затем каким-то образом проверить, не пуст ли этот файл.

Любые идеи?


person Slavatron    schedule 29.01.2015    source источник
comment
Выходит ли он с кодами выхода успеха/неудачи или вывод отличается только тем, печатается он или нет?   -  person Etan Reisner    schedule 29.01.2015
comment
bash проверяет статус выхода последней команды с помощью if [ $? -eq 0 ], после чего просто then let counter=counter+1 else exit ... etc. Хотя @rici - отличный подход - таким образом вам не нужно беспокоиться о касании скриптов.   -  person G. Cito    schedule 29.01.2015


Ответы (2)


Вы можете записать вывод в переменную, а затем выйти из цикла, если эта переменная имеет нулевую длину.

while [ $counter -lt 250 ]; do
    perl Cumulative_Percentage.pl TP53.lst T1_endo.maf >> OutFile
    output=$(perl Optimize_Panel.pl TP53.LST T1_endo.maf)
    [ -z "$output" ] && break
    echo "$output" >> TP53.lst 
    let counter=counter+1
done
person Markku K.    schedule 29.01.2015

Простой хак (на случай, если perl-скрипт не выдает значимого статуса выхода):

perl Optimize_Panel.pl TP53.LST T1_endo.maf | grep . >> TP53.lst || break

grep . соответствует любой непустой строке, поэтому это способ удаления пустых строк. Но это также способ определить, были ли какие-либо непустые строки; он выйдет из строя именно в том случае, когда их не было. Конечно, было бы намного лучше, если бы perl-скрипт предоставлял соответствующий код состояния выхода (0 для успеха, ненулевое значение для неудачи), и в этом случае вы могли бы пропустить | grep . хак.)

Кстати, вы можете использовать арифметику for в bash, чтобы сделать ваш скрипт более читабельным:

for ((counter=0; counter < 250; ++counter)); do
    perl Cumulative_Percentage.pl TP53.lst T1_endo.maf >> OutFile
    perl Optimize_Panel.pl TP53.LST T1_endo.maf |
      grep . >> TP53.lst || break;
done
person rici    schedule 29.01.2015
comment
Очень приятно - это программирование оболочки, поэтому я не думаю, что это хак ... кроме как в смысле простого быстрого правильного способа сделать это. ++ - person G. Cito; 29.01.2015