나는 판게놈 파이프라인을 실행해 왔으며 roary
for 루프 안에 스크립트를 작성해야 합니다. 예를 들어 gff
다음과 같은 파일이 있습니다.
a.gff
b.gff
5.gff
101.gff
clustered_proteins
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
동일한 작업을 수행하기 위해 아래와 같이 스크립트를 작성했습니다.
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
하지만 위의 스크립트는 내 목적에 부합하지 않습니다. 스크립트가 매우 간단해서 작성하기 어렵다는 것만 알고 있습니다. 스크립트를 개선하는 데 도움을 주세요.
미리 감사드립니다.
답변1
사용 /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
먼저 위치 인수를 패턴과 일치하는 파일 이름 목록으로 설정합니다 *.gff
. 그런 다음 목록을 반복하여 변수를 name
현재 파일 이름의 값으로 설정합니다.
루프 내에서 각 파일 이름에 대해 첫 번째 위치 인수가 위치 인수 목록에서 제거됩니다. 이동된 요소는 에도 있는 현재 파일 이름에 해당합니다 $name
. 그 이후에는 shift
위치 인수 목록에 다른 파일 이름이 포함되지만 포함되지는 않습니다 $name
.
(...)
루프의 하위 쉘 에서 로컬 IFS
로 쉼표로 설정했습니다. 즉, "$*"
쉼표로 구분된 현재 위치 인수 목록으로 구성된 문자열로 확장됩니다.
그런 다음 파일 이름과 기타 파일 이름을 쉼표로 구분된 목록으로 query_pan_genome
사용하여 $name
유틸리티를 호출합니다 .
서브쉘 이후, 루프 본문이 끝나기 직전에 현재 이름이 위치 인수 목록에 다시 들어가지만 끝에 있습니다.
목록을 반복하더라도 루프 내에서 위치 인수 목록을 수정하는 데 문제가 없습니다. 우리가 반복하는 목록은 루프에서 및 를 사용하여 shift
수정한 목록의 변경 불가능한 복사본 입니다 set
( for
루프는 항상 정적 요소 목록을 반복합니다).
문제의 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
답변2
다음을 사용하는 것이 더 쉽습니다 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
어디
${array:#pattern}
패턴과 일치하지 않는 배열의 요소로 확장되므로 여기서는 Except가 사용됩니다${files#$f}
.$files
$f
${(j[,])array}
배열의 요소를 로 연결합니다,
.
대신 , glob 확장 옵션이 있는 glob 한정자를 *.gff(N)
사용하여 glob을 활성화할 수 있습니다 .*.gff(Nn)
n
numericglobsort
file10.gff
뒤쪽에 file2.gff
예를 들어.
답변3
배열을 사용하고 해당 인덱스를 반복하고 각 인덱스를 일시적으로 설정 해제할 수 있습니다.
#! /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
출력 예:
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