수치 수량자로 sed - 어떻게?

수치 수량자로 sed - 어떻게?

슬래시와 그 뒤의 모든 내용이 제거되도록 여러 파일의 fasta 헤더를 편집하려고 합니다("이후의 모든 내용"이 10자 이하인 경우). 헤더 행은 ">"로 표시됩니다.

for i in ./*.fa;do sed -r 's/(>.*)\/.\{,10\}\n/\1\n/' "$i"; done

나도 시도했다

for i in ./*.fa;do sed -r 's/(>.*)\/.{,10}\n/\1\n/' "$i"; done

하지만 상황은 나아질 기미가 보이지 않습니다. 내 직감으로는 {,10} 수량자가 모든 것을 깨뜨린다는 것입니다. 하지만 잘 모르겠습니다. 도와주셔서 감사합니다!

예를 들어, 파일에 다음이 포함되어 있는 경우:

>header1_some_extra_data_here/1-1000
ATGCGGGTACCCCA
>code/header2_some_extra_data
AGGTCCCCGGGAAAAA

출력이 다음과 같기를 원합니다.

>header1_some_extra_data_here
ATGCGGGTACCCCA
>code/header2_some_extra_data
AGGTCCCCGGGAAAAA

답변1

sed입력 데이터에서 개행 문자를 일치시킬 수 없기 때문에 교체가 예상대로 작동하지 않습니다 . 이는 sed파일이 한 줄씩 읽혀지기 때문입니다 . 즉, 줄 바꿈을 구분 기호로 사용하고 표현식은 구분 줄 바꿈을 사용하지 않고 줄에 개별적으로 적용됩니다.

대신 코드를 약간 변경하세요.

for fasta in ./*.fa; do
    sed 's;^\(>.*\)/.\{0,10\}$;\1;' "$fasta"
done

내가 변경한 사항은 다음과 같습니다.

  1. 기본값 대신 명령 ;의 구분 기호 로 사용됩니다 . 이로 인해 우리는 패턴의 문제 에서 벗어날 수 없게 됩니다 . 거의 모든 문자를 구분 기호로 사용할 수 있지만 패턴이나 대체 텍스트에 표시되지 않는 문자를 선택해야 합니다.s/////
  2. 표준 기본 정규식 구문을 사용하세요. 패턴에서 (...)확장 정규식 구문은 \{...\}기본 정규식 구문입니다. 이식성을 위해 기본 구문을 사용하기로 결정했습니다. 이는 또한 -rGNU에서 확장 구문을 활성화하는 옵션을 포기한다는 의미이기도 합니다 sed.
  3. 패턴을 사용하여 선의 시작과 ^끝 부분 에 각각 고정합니다 $.
  4. 대체 비트에 개행 문자를 삽입하려고 하지 마세요.

sed그것을 표현하는 또 다른 짧은 방법은 다음과 같습니다.

sed '/^>/s;/.\{0,10\}$;;'

>그러면 해당 문자로 시작하는 모든 줄 에 대체가 적용됩니다 ( /^>/후속 명령의 "주소" 역할 s///). 교체는 단순히 /줄 끝까지 이어지는 비트를 삭제합니다.만약에이 비트의 길이는 10자 이하입니다.

답변2

다음은 약간 다른 접근 방식입니다.

  1. 출력을 새 파일에 저장합니다.

    for file in *fa; do 
         sed -E 's|^\s*(>.{10,}.*)/.*|\1|' "$file" > "$file.fixed"; 
     done
    
  2. 해당 위치에서 파일을 편집합니다.

    sed -i -E 's|^\s*(>.{10,}.*)/.*|\1|' *.fa 
    

-E옵션을 사용하면 확장 정규식을 사용할 수 있습니다. 이를 통해 ()캡처 및 {}반복을 이스케이프하지 않고 사용할 수 있습니다 . 명확성을 위해 구분 기호를 로 변경 |하고 추가했습니다 ^\s*(귀하의 지원이 지원되지 않을 수 있습니다 sed. 그렇지 않은 경우 ^ *때로는 앞에 공백이 있을 수 있으므로 대신 사용할 수 있습니다 >). 왜냐하면 때때로 fasta 파일에 있기 때문입니다.

그런 다음 비결은 a >뒤에 10개 이상의 문자를 a 까지 일치시키고 /해당 문자를 괄호로 묶어 일치하도록 캡처한 \1다음 전체 줄을 일치하는 부분으로 바꾸는 것입니다.

이렇게 하면 가장 긴 10자를 초과하여 마지막 문자까지 찾습니다 /. 따라서 동일한 행이 여러 개 있으면 /마지막 행을 제외한 모든 행이 유지됩니다. 예를 들어:

$ echo ">header1_some_extra_data_here/1-1000/foo/bar/baz" | 
    sed -E 's|^\s*(>.{10,}.*)/.*|\1|' 
>header1_some_extra_data_here/1-1000/foo/bar
    

이를 방지하고 첫 번째 문자 뒤의 모든 항목을 제거하려면 /(10자 일치하는 경우) 다음을 사용하십시오.

sed -E 's|^\s*(>.{10}[^/]*)/.*|\1|'

관련 정보