같은 줄에 있는 문자열의 일부로 문자열을 바꾸는 방법은 무엇입니까?

같은 줄에 있는 문자열의 일부로 문자열을 바꾸는 방법은 무엇입니까?

내 Linux 컴퓨터에 아래와 같은 파일이 있지만 gene_id잘못되었습니다. 그래서 "PB"문자열을 같은 줄에 있는 문자열로 바꾸고 싶습니다 gene_id.transcript_id

$ cat try.gff

transcript  30351   32332   .   +   .   gene_id "PB"; transcript_id "PB.1.66";
exon    30351   31677   .   +   .   gene_id "PB"; transcript_id "PB.1.59";
exon    31758   31871   .   +   .   gene_id "PB"; transcript_id "PB.1.40";
exon    31968   32178   .   +   .   gene_id "PB"; transcript_id "PB.1.30";
exon    32257   32332   .   +   .   gene_id "PB"; transcript_id "PB.1.20";
transcript  30351   32332   .   +   .   gene_id "PB"; transcript_id "PB.28.309";
exon    30351   31677   .   +   .   gene_id "PB"; transcript_id "PB.58.900";
exon    31758   31871   .   +   .   gene_id "PB"; transcript_id "PB.10000.1001";
exon    31968   32178   .   +   .   gene_id "PB"; transcript_id "PB.19897.1087541";
exon    32257   32332   .   +   .   gene_id "PB"; transcript_id "PB.1.11";

예상되는 결과

transcript  30351   32332   .   +   .   gene_id "PB.1"; transcript_id "PB.1.66";
exon    30351   31677   .   +   .   gene_id "PB.1"; transcript_id "PB.1.59";
exon    31758   31871   .   +   .   gene_id "PB.1"; transcript_id "PB.1.40";
exon    31968   32178   .   +   .   gene_id "PB.1"; transcript_id "PB.1.30";
exon    32257   32332   .   +   .   gene_id "PB.1"; transcript_id "PB.1.20";
transcript  30351   32332   .   +   .   gene_id "PB.28"; transcript_id "PB.28.309";
exon    30351   31677   .   +   .   gene_id "PB.58"; transcript_id "PB.58.900";
exon    31758   31871   .   +   .   gene_id "PB.10000"; transcript_id "PB.10000.1001";
exon    31968   32178   .   +   .   gene_id "PB.19897"; transcript_id "PB.19897.1087541";
exon    32257   32332   .   +   .   gene_id "PB.1"; transcript_id "PB.1.11";

코드로 대체할 올바른 텍스트를 얻었습니다.awk -F";" '{gsub(" transcript_id ","");print $2}' try.gff | sed 's/"//g' | cut -d '.' -f 1,2

PB.1
PB.1
PB.1
PB.1
PB.1
PB.28
PB.58
PB.10000
PB.19897
PB.1

"PB"부품을 부품으로 교체하려면 어떻게 해야 합니까 gene_id?

답변1

sed모든 Unix 시스템의 모든 쉘에서 any를 사용하십시오.

$ sed 's/\(.*gene_id "\)[^"]*\(.*"\([^.]*\.[^.]*\).*\)/\1\3\2/' try.gff
transcript  30351   32332   .   +   .   gene_id "PB.1"; transcript_id "PB.1.66";
exon    30351   31677   .   +   .   gene_id "PB.1"; transcript_id "PB.1.59";
exon    31758   31871   .   +   .   gene_id "PB.1"; transcript_id "PB.1.40";
exon    31968   32178   .   +   .   gene_id "PB.1"; transcript_id "PB.1.30";
exon    32257   32332   .   +   .   gene_id "PB.1"; transcript_id "PB.1.20";
transcript  30351   32332   .   +   .   gene_id "PB.28"; transcript_id "PB.28.309";
exon    30351   31677   .   +   .   gene_id "PB.58"; transcript_id "PB.58.900";
exon    31758   31871   .   +   .   gene_id "PB.10000"; transcript_id "PB.10000.1001";
exon    31968   32178   .   +   .   gene_id "PB.19897"; transcript_id "PB.19897.1087541";
exon    32257   32332   .   +   .   gene_id "PB.1"; transcript_id "PB.1.11";

정규식 섹션에서 각각은 \(match로 구성된 캡처 그룹을 시작합니다 \). 교체 섹션에서 Every는 \<digit>캡처 그룹의 정규식 세그먼트와 일치하는 문자열을 참조합니다. so는 \1일치하는 문자열 \(.*gene_id "\)등을 참조합니다. 나머지는 단지 기본적인 정규식 세그먼트입니다(예: .*모든 문자의 0개 이상의 반복을 나타내고, 를 [^"]*제외한 모든 문자의 0개 이상의 반복을 나타내고 ", \.리터럴을 나타냄 .).

답변2

사용sed

$ sed 's/"[A-Z]\+\("[^"]*\(.*\)\..*\)/\2\1/' input_file
transcript  30351   32332   .   +   .   gene_id "PB.1"; transcript_id "PB.1.66";
exon    30351   31677   .   +   .   gene_id "PB.1"; transcript_id "PB.1.59";
exon    31758   31871   .   +   .   gene_id "PB.1"; transcript_id "PB.1.40";
exon    31968   32178   .   +   .   gene_id "PB.1"; transcript_id "PB.1.30";
exon    32257   32332   .   +   .   gene_id "PB.1"; transcript_id "PB.1.20";
transcript  30351   32332   .   +   .   gene_id "PB.28"; transcript_id "PB.28.309";
exon    30351   31677   .   +   .   gene_id "PB.58"; transcript_id "PB.58.900";
exon    31758   31871   .   +   .   gene_id "PB.10000"; transcript_id "PB.10000.1001";
exon    31968   32178   .   +   .   gene_id "PB.19897"; transcript_id "PB.19897.1087541";
exon    32257   32332   .   +   .   gene_id "PB.1"; transcript_id "PB.1.11";

답변3

사용행복하다(이전 Perl_6)

간단한 방법(TSV 파일 gff형식 가정):

raku -e 'my @a = lines>>.split("\t").flat; @a[7,17,27...*] = @a[9,19,29...*];    \
         @a[7,17,27...*].=comb(/ <alpha>+ \. <digit>+ /).=map(q["] ~ * ~ q["]);  \
         .put for @a.rotor(10)>>.join("\t");'  

위의 코드는 단순히 각 탭과 10개의 요소를 완전한 선형 배열 (10행 x 10열 = 100개 요소) line로 분할합니다. 8번째 열 (0 인덱스 = 7)마다 10번째 열 (0 인덱스 = 9)이 덮어쓰여집니다. 힌트를 충분히 주면 Raku가 나머지 색인 순서를 알아낼 것입니다.\tflatgene_idtranscript_id

transcript_id전체 내용을 복사한 후에는 필요한 문자를 comb꺼내어 따옴표로 묶은 다음 10개 요소마다 10 x 10 테이블을 다시 작성하는 것이 간단합니다 .<alpha>+ \. \d+q["] ~ * ~ q["]rotor


순수 정규식 방식(어려움):

~$ raku -pe 's/ <?after ^ .+? gene_id \s \" > (.+?)  (\"\; \s transcript_id \s \")  (<alpha>+ \. \d+) <?before \.> /$2$1$2/;' try.gff

또는

~$ raku -pe 's/  <?after ^ .+? gene_id \s \c[QUOTATION MARK] > (.+?)  (\c[QUOTATION MARK] \; \s transcript_id \s \")  (<alpha>+ \. \d+) <?before \.> /$2$1$2/;' try.gff

여기에서는 Raku의 자동 인쇄 라인별 플래그가 -pe익숙한 대체 연산자와 s///결합되어 사용됩니다. 5개의 정규식 원자를 검색하고 괄호로 3개의 원자를 캡처합니다.

  1. 문자열의 시작 부분을 <?after … >대상으로 하는 너비가 0인 정방향 검색 (후행 공백 및 따옴표 포함),^gene_id \s \"
  2. [캡처됨 $0] 탐욕스럽지 않은 .+?문자를 한 번 이상, 즉 자체를 폐기합니다 gene_id.
  3. [captured as]는 $1줄의 해당 부분(주변 공백 및 구두점 포함)의 텍스트를 포함합니다.transcript_id
  4. [캡처] $2다음 중 원하는 부분을<alpha>+ \. \d+transcript_id
  5. 너비가 0인 긍정적인 예측은 <?before … >두 번째 지점 이전의 이전 캡처를 중지합니다 \..

마지막으로 교체에서는 $2캡처를 캡처로 바꿉니다 $0. $1캡처가 정상 $2위치로 돌아갑니다.

입력 예:

transcript  30351   32332   .   +   .   gene_id "PB"; transcript_id "PB.1.66";
exon    30351   31677   .   +   .   gene_id "PB"; transcript_id "PB.1.59";
exon    31758   31871   .   +   .   gene_id "PB"; transcript_id "PB.1.40";
exon    31968   32178   .   +   .   gene_id "PB"; transcript_id "PB.1.30";
exon    32257   32332   .   +   .   gene_id "PB"; transcript_id "PB.1.20";
transcript  30351   32332   .   +   .   gene_id "PB"; transcript_id "PB.28.309";
exon    30351   31677   .   +   .   gene_id "PB"; transcript_id "PB.58.900";
exon    31758   31871   .   +   .   gene_id "PB"; transcript_id "PB.10000.1001";
exon    31968   32178   .   +   .   gene_id "PB"; transcript_id "PB.19897.1087541";
exon    32257   32332   .   +   .   gene_id "PB"; transcript_id "PB.1.11";

예제 출력:

transcript  30351   32332   .   +   .   gene_id "PB.1"; transcript_id "PB.1.66";
exon    30351   31677   .   +   .   gene_id "PB.1"; transcript_id "PB.1.59";
exon    31758   31871   .   +   .   gene_id "PB.1"; transcript_id "PB.1.40";
exon    31968   32178   .   +   .   gene_id "PB.1"; transcript_id "PB.1.30";
exon    32257   32332   .   +   .   gene_id "PB.1"; transcript_id "PB.1.20";
transcript  30351   32332   .   +   .   gene_id "PB.28"; transcript_id "PB.28.309";
exon    30351   31677   .   +   .   gene_id "PB.58"; transcript_id "PB.58.900";
exon    31758   31871   .   +   .   gene_id "PB.10000"; transcript_id "PB.10000.1001";
exon    31968   32178   .   +   .   gene_id "PB.19897"; transcript_id "PB.19897.1087541";
exon    32257   32332   .   +   .   gene_id "PB.1"; transcript_id "PB.1.11";

https://docs.raku.org/언어/regexes
https://raku.org

관련 정보