while 루프에서 변수가 이상하게 동작합니다.

while 루프에서 변수가 이상하게 동작합니다.

재포스팅입니다생물정보학에서도 같은 문제가 발생합니다.. 제공된 답변이 저에게 적합하지 않아 여기에 문의해야 한다고 생각했습니다.

내 디렉토리는 여러 프로젝트 디렉토리가 있는 기본 디렉토리("mgp"로 시작)로 구성됩니다. 각 프로젝트 디렉토리에는 여러 개의 메타게놈 디렉토리가 있습니다("mgm"으로 시작하고 ".3"으로 끝남). 각 메타게놈 디렉터리에는 항상 텍스트 .fna(fasta) 파일이 있습니다. Fasta 파일은 다음 구조로 정의됩니다.

>Header1
Sequence1
>Header2
Sequence2

내가 원하는 것은 이러한 모든 fasta 파일을 살펴보고 프로젝트 및 메타게놈 디렉터리에 해당하는 헤더 코드에 추가하는 루프입니다. 예를 들어 프로젝트 디렉터리 mgp83581의 fasta 파일, 메타게놈 하위 디렉터리 mgm4729322.3에 다음 헤더가 있는 경우...

>seq1
>seq2

...다음으로 변경하고 싶습니다.

>83581_322_seq1
>83581_322_seq2

기본적으로 프로젝트와 관련된 숫자 코드와 메타게놈과 관련된 7자리 코드 중 마지막 세 자리(파일명의 ".3" 부분 제외)를 추가하고 싶습니다. 코드의 이 부분은 괜찮습니다. 한 번에 하나의 파일만 처리할 수 있다는 것을 알고 있습니다.

이것이 내가 지금 가지고 있는 완전한 코드입니다. 이것은 작동하지 않습니다. (두 개의 테스트 파일 중 하나에서만 작동합니다)

ls mgp*/mgm*.3/*.fna |  while read line ; do
        header=$(sed -r "s/^mgp([0-9]*)\/mgm[0-9]{4}([0-9]{1,})\.3\/(mgm.*\.fna)/\1_\2/") #this is where I get the code I want from the path
        sed -i.bak "s/^>/>${header}_/" $line  #this is where I add said code to my file
done

개별적으로 살펴보면 코드의 일부가 작동하는 것처럼 보입니다. 내가 쓴다면

ls mgp*/mgm*.3/*.fna | while read line ; do
        echo $line
done

...그런 다음 관심 있는 두 테스트 파일의 경로를 복구할 수 있었습니다. 내가 쓴다면 :

ls mgp*/mgm*.3/*.fna | while read line ; do
    echo $line
    header=$(sed -r "s/^mgp([0-9]*)\/mgm[0-9]{4}([0-9]{1,})\.3\/(mgm.*\.fna)/\1_\2/")
    echo $header
done

...그리고 뭔가 꽤 이상한 걸 발견했어요. 나는 얻다:

path for file#1
header for file #2

그러나 나는 다음을 얻을 것으로 기대합니다.

path for file#1
header for file#1
path for file#2
header for file#2

while 루프의 변수가 어떻게 조금 이상하게 동작할 수 있는지에 대한 이전 질문/답변을 본 적이 있지만 작업을 수행할 만큼 충분히 이해하지 못하는 것 같습니다.

답변1

주요 문제는 sed런타임에 입력을 제공하지 않는다는 것입니다. 즉, 전달한 파일 이름이 포함된 주변 루프에서 상속된 stdin 스트림을 읽습니다 ls(첫 번째 반복에서 모두). 또 다른 문제는 목록 파일을 사용하고 있다는 것입니다 ls(출력을 올바르게 읽는 것보다 파일 이름을 반복하는 것이 더 쉽고 안전합니다 ls). 또한 사용 중인 다소 복잡한 정규식을 고려하면 코드를 읽기가 약간 어렵습니다.


파일을 반복하려면 다음을 사용하십시오.

for pathname in mgp*/mgm*.3/*.fna; do
   # ... use "$pathname" here ...
done

fasta 파일의 경로명이 주어지면 하위 디렉토리 이름에서 3자리 게놈 코드를 얻으려면 다음을 수행하십시오 $pathname.

genome=${pathname%.3/*.fna}     # trim off tail
genome=${genome#mgp*/mgm????}   # trim off head

322예를 들어 in $genomefrom mgp83581/mgm4729322.3/blah.fnain 을 제공합니다 $pathname.

같은 방법으로 프로젝트 번호를 가져옵니다.

project=${pathname%/mgm*.3/*.fna}   # trim off tail
project=${project#mgp}              # trim off head

그것은 $project83581것이고 $genome입니다 322.

>모든 fasta 파일에서 줄이 시작될 때마다 이를 삽입하려면 다음을 수행하십시오.

for pathname in mgp*/mgm*.3/*.fna; do
    genome=${pathname%.3/*.fna}     # trim off tail
    genome=${genome#mgp*/mgm????}   # trim off head

    project=${pathname%/mgm*.3/*.fna}   # trim off tail
    project=${project#mgp}              # trim off head

    sed -i .old "s/^>/>${project}_${genome}_/" "$pathname"
done

이렇게 하면 접미사가 붙은 오래된 파일도 추가로 백업됩니다 .old.

참고: 에복사당신의 데이터. 사용 가능한 fasta 파일이 없으며 최종 루프를 테스트하지 않았습니다.

관련 정보