2011-09-01 3 views
1

이름에 배열 요소가 포함되어 있는지 여부에 따라 두 개 이상의 파일을 연결하고 싶습니다.Bash : 배열 변수를 기반으로하는 고양이

내가 라인으로 파일 라인의이 종류를 읽고있다 (proteome.pisa) : 각 라인에 대한

2PJY_p chain=(B C) hresname=() hresnumber=() hatom=() model=() altconf=() 
2Q7N_p chain=(A E F G H I J K L) hresname=(FUC MAN NAG) hresnumber=() hatom=() model=() altconf=() 

이 스크립트는 첫 번째 열에서 문자열을 추출하고 변수 pdbid로 정의합니다. 그런 다음 두 번째 열을 가져 와서 배열 (요소 $ c의 체인)로 정의합니다. 그런 다음 $ {pdbid} _ $ {c} _p.pdb라는 파일이 있는지 확인한 다음 해당 파일의 내용을 $ {pdbid} _p _ $ {chains} .pdb 파일에 병합합니다.

스크립트 :

while read line ; do 

echo "$line" > pdb.line 
cut -f1 pdb.line > pdb.list 
sed -i 's/.*/\"&\"/' pdb.list 
sed -i 's/_p//g' pdb.list 
awk '{ printf "pdbid="; print }' pdb.list > pdbid.list 

cut -f2 pdb.line > chain.list 

source pdbid.list 
source chain.list 

chains=`printf "%s" "${chain[@]}"` 

for c in ${chain[@]} ; do 
if [ ${#chain[@]} -gt 1 ] && \ 
    [ -f ${pdbid}_${c}_p.pdb ] ; then 
cat ${pdbid}_${chain[$c]}_p.pdb >> ${pdbid}_p_${chains}.pdb 
fi 
done 

done < proteome.pisa 

이 예상되는 동작은 2PJY_p_BC.pdb라는 파일의 첫 번째 행, 2PJY_p_B.pdb 및 2PJY_p_C.pdb을 위해, 예를 들어 병합하는 것이 었습니다. 그러나 실제로는 첫 번째 파일을 두 번 병합합니다. 나는 이유를 이해할 수 없다 ...

+1

변수의 값을 디버깅하는 데'set -vx'를 사용하고 있습니까? 행운을 빕니다. – shellter

답변

1

이것은 훌륭한 질문이다. 왜냐하면 배쉬는 모든 것을 혼자서 할 수는 없다는 것을 보여주기 때문이다. 대신 awk, cut 등의 도우미가 필요합니다 ... 나는 여러분의 솔루션을 살펴본 결과 두 소스 라인 이후에 pdbid, chain 및 chains 변수가있을 것으로 예상됩니다. 그러나 스크립트가 올바르게 설정하지 않았으므로 그 부분을 도와 드릴 수 있습니다. 나는 Perl을 그다지 알지 못하지만 Perl이이 경우에 잘 작동한다고 생각한다. 여기 makevars.pl입니다 :

while (<STDIN>) { 
    my($line) = $_; 
    if ($line =~ /^(.*)_p.*chain=\((.*)\).*hresname.*$/) { 
     print "pdbid=$1\n"; 
     print "chain=($2)\n"; 
     $chains = $2; 
     $chains =~ s/ //g; 
     print "chains=$chains\n"; 
    } 
} 

그리고 여기 쉘 스크립트입니다

while read line 
do 

    echo "$line" | perl makevars.pl >setvars.sh 
    source setvars.sh 
    # Now, pdbid, chain, and chains are set, do your things 

done < proteome.pisa 

도움이 되었기를 바랍니다. 그것을 변경

cat ${pdbid}_${chain[$c]}_p.pdb >> ${pdbid}_p_${chains}.pdb 

행 :

cat ${pdbid}_${c}_p.pdb >> ${pdbid}_p_${chains}.pdb 

문제를 해결하기 위해 표시

+0

이 펄 솔루션에 감사드립니다. 나는 그것을 시도 할 것이다. – mirix

0

문제점이 라인 어레이의 정의 것으로 보인다.

또한 "$ {chain [@]}"을 모두 인용 부호로 묶었습니다.

1

나는 입력을보다 간단한 형태로 sed으로 전처리 한 다음 그 위에 반복 할 것을 제안합니다. 이것은 chain=(...)이 항상 해당 행의 첫 번째 속성이라고 가정합니다.

#!/bin/sh 

# Replace 2ICQ_p chain=(A B C ... Z) attribs= ... with 
# 2ICQ_p A B C ... Z 
sed 's/ chain=\(//;s/\).*//' <proteome.pisa | 
while read pdbid chain; do 
    chains=${chain/ /} 
    for c in $chain; do 
     test -e ${pdbid}_${c}_p.pdb || continue 
     cat ${pdbdid}_${c}_p.pdb 
    done >${pdbid}_p_${chains}.pdb 
done 

이렇게하면 첫 번째 스크립트를 완성시키는 임시 파일을 사용하지 않아도됩니다. 생성 된 파일을 소싱하는 것은 놀랄 일이 아니라면 놀랄 것입니다 (대개 그런 종류의 백틱을 사용할 수 있지만 실제로는 필요하지 않습니다).

sed의 여러 변형이 있습니다. 일부 (예 : Linux)는 리터럴 괄호를 백 슬래시로 사용하고 다른 일부는 (예 : Mac OSX) 사용하지 않습니다. 그래도 작동하지 않으면 백 슬래시를 꺼내보십시오.

read 여러 변수 이름을 사용하면 첫 번째 변수 이름이 첫 번째 토큰 등을 수신하도록 공백의 입력을 분할합니다. 마지막으로 명명 된 변수는 공백 분할을 추가하지 않고 남아있는 것을받습니다. continuefor 또는 while 루프의 다음 반복으로 점프합니다. 그것 이외에, 이것은 상당히 자명하다. 순수한 Bourne 쉘에서이 모든 작업을 수행하도록 압박을 받았다면 처음에는 sed 교체가 대체 문자열 대체와 관련된 것으로 대체 될 수 있습니다.

관련 문제