【问题标题】:How to use for loop with multiple variables in linux如何在linux中使用带有多个变量的for循环
【发布时间】:2019-01-28 14:08:41
【问题描述】:

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

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

感谢您的帮助。

【问题讨论】:

  • 您可以使用一对数组(即目标和法线),其中对在两个数组中占据相同的位置。
  • 那么这会涉及到两个循环遍历每个数组吗?
  • 很难说你的代码有什么问题,因为你没有提供它或者你遇到的错误。另见How to create a Minimal, Complete, and Verifiable examplebash shell nested for loop 的可能重复项
  • 我对此没有任何错误,因为我不知道如何创建一个将特定变量配对在一起的 for 循环,而不仅仅是循环一组变量或所有可能的组合。我不认为它是一个简单的嵌套循环,因为我有一个应该一起运行的 TARGET_SAMPLE 和 NORMAL_SAMPLE 可能组合的硬编码列表。
  • 不,只有一个循环。说normal=(n1 n3 n3)target=(t2 t3 t4)。两个数组都有三个元素。只要您保持您感兴趣的顺序,您就可以使用变量 n 从 0 循环到长度(正常)并使用 ${normal[n]}${target[n]} 作为参数。

标签: arrays linux bash for-loop


【解决方案1】:

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

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 循环,但保持数组同步很容易出错,因此我不推荐它。

【讨论】:

  • cat file | while read ... 写得更好while read; do ... done &lt; file
  • 方法 1 效果很好,但是有时我必须使用 bsub 将命令提交到 LSF,如果我不使用 export TARGET_SAMPLE="sample_1" 导出变量,它就不起作用,是否有使用方法 1 导出变量的方法?抱歉,如果不是很清楚。
  • 点了。猫旨在作为占位符。它可能是更复杂的东西,比如 grep 的输出或数据库查询或更长的管道。
猜你喜欢
  • 2014-06-12
  • 2014-06-21
  • 2021-04-23
  • 2022-11-15
  • 2017-09-04
  • 2013-08-31
  • 2011-05-06
  • 2015-12-12
  • 2016-05-10
相关资源
最近更新 更多