bash - 带有空变量的 Else-If Satement 不起作用
问题描述
我正在尝试在 shell/bash 脚本中编写一个 if-else 条件,该条件将用于许多不同的文件,因此它不适合某种结构。
我有三个不同的文件,并且从这些文件中的每个文件中选择了最多三个不同的变量,这些变量进入 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}" ]
非缺失,但这也不起作用。也试过[[ ]]
比较[ ]
,但还是一样。
有什么我明显遗漏的吗?
解决方案
我不确定我是否理解逻辑应该如何工作,但我认为你可能对德摩根定律有疑问,这与逻辑否定与 AND 和 OR 的结合方式有关。英语在这方面往往很草率,所以当你把你想要的东西翻译成代码逻辑时,你必须仔细考虑。具体来说,你说的是“第一个条件:如果所有变量都不为空”,但是对应的if
语句:
if [ "${ANC3}" != "" ] || [ "${ANC31}" != "" ] || [ "${ANC35}" != "" ]; then
..实际上对应于“如果任何变量不为空”。
在您给出的示例中,ANC3
并且ANC31
都是空的(所以前两个测试返回为假),并且ANC35
不是空的(它是“SAS”),所以第三个测试是真的。false || false || true
计算结果为真,因此if
整个条件为真,并且该if
语句的分支将被执行。如果只有一个变量为非空,这是否应该发生?
如果我对这个问题是正确的,那么第一个if
语句应该有&&
s 而不是||
s,如下所示:
if [ "${ANC3}" != "" ] && [ "${ANC31}" != "" ] && [ "${ANC35}" != "" ]; then
测试也可能存在类似的问题elif
,但正如我所说,我不确定我是否理解它应该正确执行的操作。
推荐阅读
- python - reqMktData() - app.run() 调用后如何提交新的快照请求?
- python - Pandas 中组内的交替值
- aws-lambda - 带有 API 代理的 AWS Lambda
- vuejs2 - Vuex 在从后端分页的数据上下文中的用途是什么
- php - 如何在php中结合分页和过滤?
- apache-spark - Spark窄化改造能否产生re-shuffle?
- docker - 在 Gitlab Container Registry 中看不到容器镜像
- php - 如何让 Ratchet WebSocket 保持活动状态?
- git - 无法使用 git 将文件添加到 stage 与 `git add .`:zsh 进入文本编辑器模式
- javascript - Paypal SDK 没有收钱