如何在单个 for 循环中分配两个变量?

Kum*_*mar 3 shell bash shell-script

我一直在运行roarypangenome管道,我需要在for循环中编写一个脚本,例如我有一个gff文件如下,

a.gff
b.gff
5.gff
101.gff
clustered_proteins
Run Code Online (Sandbox Code Playgroud)

我需要运行一个命令来从roary管道中检索独特的基因,如下所示,

query_pan_genome -a difference --input_set_one a.gff --input_set_two b.gff,5.gff,101.gff -g clustered_proteins
 
query_pan_genome -a difference --input_set_one b.gff --input_set_two a.gff,5.gff,101.gff -g clustered_proteins

query_pan_genome -a difference --input_set_one 5.gff --input_set_two a.gff,b.gff,101.gff -g clustered_proteins

query_pan_genome -a difference --input_set_one 101.gff --input_set_two a.gff,b.gff,5.gff -g clustered_proteins
Run Code Online (Sandbox Code Playgroud)

为了做同样的事情,我写了一个脚本如下,

file1=*.gff
file2=*.gff
file3="-f "$file1-$file2"
for file in *.gff
do
query_pan_genome -a difference --input_set_one "$file1" --input_set_two "$file3" -g clustered_proteins 
done
Run Code Online (Sandbox Code Playgroud)

但是上面的脚本并没有达到我的目的,我只知道简单的脚本,这对我来说很难写。请帮助我使脚本完美。

提前致谢。

Kus*_*nda 6

使用/bin/sh

#!/bin/sh

set -- *.gff
for name do
    shift
    (   IFS=,
        query_pan_genome -a difference \
            --input_set_one "$name" \
            --input_set_two "$*" \
            -g clustered_proteins
    )
    set -- "$@" "$name"
done
Run Code Online (Sandbox Code Playgroud)

这首先将位置参数设置为匹配模式的文件名列表*.gff。然后循环遍历这个列表,将变量设置name为当前文件名的值。

在循环中,对于每个文件名,第一个位置参数从位置参数列表中移出。这个移出的元素对应于也在$name. 在 之后shift,位置参数列表包含其他文件名,但不包含$name.

(...)循环的子shell中,我们在本地设置IFS为逗号。这意味着"$*"将扩展为一个字符串,该字符串由当前的位置参数列表组成,并以逗号作为分隔符。

然后我们query_pan_genome使用$name文件名和其他作为逗号分隔的列表调用该实用程序。

在子shell之后,就在循环体结束之前,当前名称被放回到位置参数列表中,但在最后。

修改循环内的位置参数列表没有问题,即使我们正在迭代这个列表。我们迭代的列表是我们在循环中使用shiftand修改的列表的不变副本setfor循环总是迭代元素的静态列表)。

鉴于问题中的 GFF 文件列表,上面的代码最终将执行以下四个命令:

query_pan_genome -a difference --input_set_one 101.gff --input_set_two 5.gff,a.gff,b.gff -g clustered_proteins
query_pan_genome -a difference --input_set_one 5.gff --input_set_two a.gff,b.gff,101.gff -g clustered_proteins
query_pan_genome -a difference --input_set_one a.gff --input_set_two b.gff,101.gff,5.gff -g clustered_proteins
query_pan_genome -a difference --input_set_one b.gff --input_set_two 101.gff,5.gff,a.gff -g clustered_proteins
Run Code Online (Sandbox Code Playgroud)


mur*_*uru 5

您可以使用数组,循环遍历其索引并暂时取消设置每个索引:

#! /bin/bash

input_files=(*.gff)

IFS=,
for index in "${!input_files[@]}"
do
    input_file=${input_files[$index]}
    unset input_files[$index]
    echo "$input_file" "${input_files[*]}"
    input_files[$index]=$input_file
done
Run Code Online (Sandbox Code Playgroud)

示例输出:

101.gff 5.gff,a.gff,b.gff
5.gff 101.gff,a.gff,b.gff
a.gff 101.gff,5.gff,b.gff
b.gff 101.gff,5.gff,a.gff
Run Code Online (Sandbox Code Playgroud)


Sté*_*las 5

使用zsh以下方法更容易:

#! /bin/zsh -
files=(*.gff(N))

# don't run that command if there are fewer than 2 files
(( $#files < 2 )) ||
  for f ($files)
    query_pan_genome -a difference \
                     --input_set_one $f \
                     --input_set_two ${(j[,])files:#$f} \
                     -g clustered_proteins
Run Code Online (Sandbox Code Playgroud)

在哪里

  • ${array:#pattern}扩展为与模式不匹配的数组元素,因此这里使用except${files#$f}的元素。$files$f
  • ${(j[,])array}将数组的元素与,.

相反的*.gff(N),你可能要使用*.gff(Nn)其中n的水珠预选赛轮流numericglobsort为一个水珠的扩展选项,这样file10.gff之后 file2.gff的实例。