首页 > 解决方案 > 如何在linux中使用带有多个变量的for循环

问题描述

我有一个命令需要为多个文件组合运行。该命令如下所示:

myscript.pl -output_directory /path/output_"$TARGET_SAMPLE"_vs_"$NORMAL_SAMPLE" -target_sample /path/$TARGET_SAMPLE.bam -normal_sample /path/$NORMAL_SAMPLE.bam

我想为多组样本运行它,而不必每次都手动更改路径。现在我在手动运行之前设置样本,如下所示:

export TARGET_SAMPLE="sample_1"
export NORMAL_SAMPLE="sample_2"

如何运行它以确保 TARGET_SAMPLE 和 NORMAL_SAMPLE 始终正确匹配?对于每个 NORMAL_SAMPLE,我需要使用两个不同的 TARGET_SAMPLE 文件运行脚本两次。我认为使用数组可以工作,但我不知道如何正确地将其输入到 for 循环中。

以下是我需要运行的一些配对示例:

export TARGET_SAMPLE="sample_1"
export NORMAL_SAMPLE="sample_2"

export TARGET_SAMPLE="sample_3"
export NORMAL_SAMPLE="sample_2"

export TARGET_SAMPLE="sample_4"
export NORMAL_SAMPLE="sample_5"

export TARGET_SAMPLE="sample_6"
export NORMAL_SAMPLE="sample_5"

因此,此组合列表的第一个示例输出将是在 shell 中提交这些命令:

myscript.pl -output_directory /path/output_sample_1_vs_sample_2 -target_sample /path/sample_1.bam -normal_sample /path/sample_2.bam

第二个是:

myscript.pl -output_directory /path/output_sample_3_vs_sample_2 -target_sample /path/sample_3.bam -normal_sample /path/sample_2.bam

谢谢你的帮助。

标签: arrayslinuxbashfor-loop

解决方案


方法 1 使用 while-loop 从“here-document”读取多个值:

export TARGET_SAMPLE NORMAL_SAMPLE

# special characters in the values (eg. space) will cause problems
while read TARGET_SAMPLE NORMAL_SAMPLE ANYTHING_ELSE; do
    # insert sanity checks here
    myscript.pl -output_directory /path/output_"$TARGET_SAMPLE"_vs_"$NORMAL_SAMPLE" -target_sample /path/$TARGET_SAMPLE.bam -normal_sample /path/$NORMAL_SAMPLE.bam
done <<'EOD'
sample_1 sample_2
sample_3 sample_2
sample_4 sample_5
sample_6 sample_5
EOD

方法 1b 与方法 1 相同,但从外部文件读取数据:

# spcial characters in the values (eg. space) will cause problems
cat >mydata <<'EOD'
sample_1 sample_2
sample_3 sample_2
sample_4 sample_5
sample_6 sample_5
EOD

export TARGET_SAMPLE NORMAL_SAMPLE

# normally $ANYTHING_ELSE should be empty but embedded spaces will confuse read
cat mydata | while read TARGET_SAMPLE NORMAL_SAMPLE ANYTHING_ELSE; do
    # insert sanity checks here
    myscript.pl -output_directory /path/output_"$TARGET_SAMPLE"_vs_"$NORMAL_SAMPLE" -target_sample /path/$TARGET_SAMPLE.bam -normal_sample /path/$NORMAL_SAMPLE.bam
done

方法2用shell函数包装:

export TARGET_SAMPLE NORMAL_SAMPLE

wrapper(){
    TARGET_SAMPLE=$1
    NORMAL_SAMPLE=$2
    # insert sanity checks here
    myscript.pl -output_directory /path/output_"$TARGET_SAMPLE"_vs_"$NORMAL_SAMPLE" -target_sample /path/$TARGET_SAMPLE.bam -normal_sample /path/$NORMAL_SAMPLE.bam
}

wrapper "sample_1" "sample_2"
wrapper "sample_3" "sample_2"
wrapper "sample_4" "sample_5"
wrapper "sample_6" "sample_5"

方法 3 在多个数组上使用 for 循环:

Bash 已索引数组变量,因此可以使用 for 循环,但保持数组同步很容易出错,因此我不推荐它。


推荐阅读