Else-If Satement с пустыми переменными не работает - PullRequest
0 голосов
/ 12 мая 2018

Я пытаюсь написать условие if-else в скрипте shell / bash, которое будет использоваться для множества различных файлов, чтобы оно не подходило для определенной структуры

У меня есть три разных файла и до трех разных переменных, выбранных из каждого из этих файлов, которые входят в оператор if-else. В моем сценарии я написал это (что, вероятно, могло бы быть написано лучше) в начале следующим образом:

ANC1=$(sed -n 1p file1 | cut -f 1 -d' ' )
ANC2=$(sed -n 2p file1 | cut -f 1 -d' ' )
ANC3=$(sed -n 3p file1 | cut -f 1 -d' ' )

ANC11=$(sed -n 1p file2 | cut -f 1 -d' ' )
ANC21=$(sed -n 2p file2 | cut -f 1 -d' ' )
ANC31=$(sed -n 3p file2 | cut -f 1 -d' ' )

ANC15=$(sed -n 1p file3 | cut -f 1 -d' ' )
ANC25=$(sed -n 2p file3 | cut -f 1 -d' ' )
ANC35=$(sed -n 3p file3 | cut -f 1 -d' ' )

Например, из этих файлов могли быть получены следующие переменные:

echo ${ANC1}
FIN
echo ${ANC2}
NFE
echo ${ANC3}


echo ${ANC11}
FIN
echo ${ANC21}
NFE
echo ${ANC31}


echo ${ANC15}
FIN
echo ${ANC25}
NFE
echo ${ANC35}
SAS 

Отсюда я написал оператор if-else (с учетом возможных отсутствующих переменных в трех файлах, как указано выше). Чтобы понять это, попытка сделать следующее:

первое условие: если все переменные не пусты; второе условие: если третья переменная является единственной отсутствующей переменной; третье условие: если третья и вторая переменные пусты

if [ "${ANC3}" != "" ] || [ "${ANC31}" != "" ] || [ "${ANC35}" != "" ]; then

    echo "***** three variables *****"

    bcftools merge -m both \
    fileref1.genotypes_${ANC1}.vcf.gz \
    fileref1.genotypes_${ANC2}.vcf.gz \
    fileref1.genotypes_${ANC3}.vcf.gz \
    -Oz \
    -o fileref1.new.genotypes_${ANC1}.${ANC2}.${ANC3}.vcf.gz

    bcftools merge -m both \
    fileref2.genotypes_${ANC11}.vcf.gz \
    fileref2.genotypes_${ANC21}.vcf.gz \
    fileref2.genotypes_${ANC31}.vcf.gz \
    -Oz \
    -o fileref2.new.genotypes_${ANC11}.${ANC21}.${ANC31}.vcf.gz

    bcftools merge -m both \
    fileref3.genotypes_${ANC15}.vcf.gz \
    fileref3.genotypes_${ANC25}.vcf.gz \
    fileref3.genotypes_${ANC35}.vcf.gz \
    -Oz \
    -o fileref1.new.genotypes_${ANC15}.${ANC25}.${ANC35}.vcf.gz

elif 
    [ "${ANC3}" == "" -a "${ANC2}" != "" ] || [ "${ANC31}" == "" -a "${ANC21}" != "" ] || [ "${ANC35}" == "" -a "${ANC25}" != "" ]; then

    echo "***** two variables *****"

    bcftools merge -m both \
    fileref1.genotypes_${ANC1}.vcf.gz \
    fileref1.genotypes_${ANC2}.vcf.gz \
    -Oz \
    -o fileref1.new.genotypes_${ANC1}.${ANC2}.vcf.gz

    bcftools merge -m both \
    fileref2.genotypes_${ANC11}.vcf.gz \
    fileref2.genotypes_${ANC21}.vcf.gz \
    -Oz \
    -o fileref2.new.genotypes_${ANC11}.${ANC21}.vcf.gz

    bcftools merge -m both \
    fileref3.genotypes_${ANC15}.vcf.gz \
    fileref3.genotypes_${ANC25}.vcf.gz \
    -Oz \
    -o fileref1.new.genotypes_${ANC15}.${ANC25}.vcf.gz

elif 
    [ "${ANC3}" == "" -a "${ANC2}" == "" ] || [ "${ANC31}" == "" -a "${ANC21}" == "" ] || [ "${ANC35}" == "" -a "${ANC25}" == "" ]; then 

    echo "***** one variable ***** "

    cp fileref1.genotypes_${ANC1}.vcf.gz fileref1.new.genotypes_${ANC1}.${ANC2}.vcf.gz

    cp fileref2.genotypes_${ANC11}.vcf.gz fileref2.new.genotypes_${ANC11}.vcf.gz

    cp fileref3.genotypes_${ANC15}.vcf.gz fileref1.new.genotypes_${ANC15}.vcf.gz

fi

Каждый раз, когда я запускаю этот скрипт, предполагается создавать 3 файла, но иногда это не так. Первая часть работает (для файлов, где все переменные не пусты), но второе и третье условия, похоже, не выполняются. Я также пробовал [ -z "${ANC3}" ] и [ -n "${ANC2}" ], чтобы указать пропущенные и не пропущенные, соответственно, но это также не сработало. Также попробовал [[ ]] по сравнению [ ] но все так же.

Что-нибудь, что я явно упускаю?

Ответы [ 2 ]

0 голосов
/ 13 мая 2018

Это не полный ответ, но вот простые POSIX примеры оболочек с заданными переменными $x, $y и $z:

первое условие: если все переменные не пусты;

[ "$x" -a "$y" -a "$z" ] && do_stuff

второе условие: если третья переменная является единственной отсутствующей переменной;

[ "$x" -a "$y" -a ! "$z" ] && do_stuff

третье условие: если третья и вторая переменные пусты

[ "$y$z" ] || do_stuff
0 голосов
/ 12 мая 2018

Я не уверен, что понимаю, как должна работать логика, но я думаю, что у вас могут быть проблемы с законами Де Моргана , которые связаны с тем, как логическое отрицание сочетается с AND и OR.,В английском это довольно неаккуратно, поэтому вам нужно тщательно подумать, когда вы переводите то, что хотите, в логику кода.В частности, вы сказали «первое условие: если все переменные не пустые», но соответствующий оператор if:

if [ "${ANC3}" != "" ] || [ "${ANC31}" != "" ] || [ "${ANC35}" != "" ]; then

.. фактически соответствует «если ЛЮБАЯ из переменных не пуста».

В приведенном вами примере ANC3 и ANC31 оба пусты (поэтому первые два теста возвращаются как ложные), а ANC35 не пуст (это «SAS»), поэтому третийтест это правда.false || false || true оценивается как true, так что условие if в целом является истинным, и эта ветвь оператора if будет выполнена.Это то, что должно происходить, когда только одна из переменных непуста?

Если я прав насчет проблемы, то первое утверждение if должно иметь && с вместо || с,например:

if [ "${ANC3}" != "" ] && [ "${ANC31}" != "" ] && [ "${ANC35}" != "" ]; then

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

...