한 줄에 gene_id와 유전자 이름이 포함된 파일이 있습니다. 다음 단어로 바꾸고 싶습니다.유전자 ID뒤에 있는 단어유전자아니면 그 이후제품아니면 그 이후스프로트(일부 누락된 경우가 있습니다.)
다음은 한 줄의 예입니다.
chrM Gnomon CDS 8345 8513 . + 1 gene_id "cds-XP_008824843.3"; transcript_id "cds-XP_008824843.3"; Parent "rna-XM_008826621.3"; Dbxref "GeneID:103728653_Genbank:XP_008824843.3"; Name "XP_008824843.3"; end_range "8513,."; gbkey "CDS"; gene "semaphorin-3F"; partial "true"; product "semaphorin-3F"; protein_id "XP_008824843.3"; sprot "sp|Q13275|SEM3F_HUMAN";
chrM StringTie exon 2754 3700 . + . gene_id "cds-YP_007626758.1"; transcript_id "cds-YP_007626758.1"; Parent "gene-ND1"; Dbxref "Genbank:YP_007626758.1,Gene "ID:15088436"; Name "YP_007626758.1"; Note "TAAstopcodoniscompletedbytheadditionof3'AresiduestothemRNA"; gbkey "CDS"; gene "ND1"; product "NADHdehydrogenasesubunit1"; protein_id "YP_007626758.1"; transl_except "(pos:3700..3700%2Caa:TERM)"; transl_table "2";
나는 다음을 달성하기 위해 sed를 사용하려고했습니다.
sed -E 's/[^gene_id] .*?;/[^gene] .*?;|[^sprot] .*?;|[^product] .*?;/g'
그러나 결과는 올바르지 않습니다.
chrM Gnomon CDS 8345 8513 . + 1 gene_id "cds-XP_008824843.3"[^gene] .*?;|[^sprot] .*?;|[^product] .*?;
chrM StringTie exon 2754 3700 . + . gene_id "cds-YP_007626758.1"[^gene] .*?;|[^sprot] .*?;|[^product] .*?;
그런데 줄을 다 저장하고 싶은데 그 뒤에 단어가 있어요.유전자 ID, 이와 같이:
chrM Gnomon CDS 8345 8513 . + 1 gene_id "semaphorin-3F"; transcript_id "cds-XP_008824843.3"; Parent "rna-XM_008826621.3"; Dbxref "GeneID:103728653_Genbank:XP_008824843.3"; Name "XP_008824843.3"; end_range "8513,."; gbkey "CDS"; gene "semaphorin-3F"; partial "true"; product "semaphorin-3F"; protein_id "XP_008824843.3"; sprot "sp|Q13275|SEM3F_HUMAN";
chrM StringTie exon 2754 3700 . + . gene_id "ND1"; transcript_id "cds-YP_007626758.1"; Parent "gene-ND1"; Dbxref "Genbank:YP_007626758.1,Gene "ID:15088436"; Name "YP_007626758.1"; Note "TAAstopcodoniscompletedbytheadditionof3'AresiduestothemRNA"; gbkey "CDS"; gene "ND1"; product "NADHdehydrogenasesubunit1"; protein_id "YP_007626758.1"; transl_except "(pos:3700..3700%2Caa:TERM)"; transl_table "2";
또는 다음과 같습니다(다른 하나를 놓친 경우).
chrM Gnomon CDS 8345 8513 . + 1 gene_id "sp|Q13275|SEM3F_HUMAN"; transcript_id "cds-XP_008824843.3"; Parent "rna-XM_008826621.3"; Dbxref "GeneID:103728653_Genbank:XP_008824843.3"; Name "XP_008824843.3"; end_range "8513,."; gbkey "CDS"; gene "semaphorin-3F"; partial "true"; product "semaphorin-3F"; protein_id "XP_008824843.3"; sprot "sp|Q13275|SEM3F_HUMAN";
chrM StringTie exon 2754 3700 . + . gene_id "ND1"; transcript_id "cds-YP_007626758.1"; Parent "gene-ND1"; Dbxref "Genbank:YP_007626758.1,Gene "ID:15088436"; Name "YP_007626758.1"; Note "TAAstopcodoniscompletedbytheadditionof3'AresiduestothemRNA"; gbkey "CDS"; gene "ND1"; product "NADHdehydrogenasesubunit1"; protein_id "YP_007626758.1"; transl_except "(pos:3700..3700%2Caa:TERM)"; transl_table "2";
어떤 도움이라도 대단히 감사하겠습니다.
답변1
gene
다음 perl 스크립트는 각 입력 라인에서 , 및 를 순서대로 일치시키려고 시도합니다 product
(즉, 제품보다 유전자를, sprots보다 제품을 우선시합니다). sprot
그 중 하나가 일치하면 일치하는 단어가 추출됩니다. 단어가 큰따옴표로 묶여 있다고 가정합니다.
일치하는 항목이 발견되면 gene_id
다음 단어를 추출된 단어로 바꿉니다.
수정 여부에 관계없이 해당 행이 인쇄됩니다.
#!/usr/bin/perl
while (<>) {
my $word = '';
if (m/\b(?:gene)\s+("[^"]*")/) {
$word = $1;
} elsif (m/\b(?:product)\s+("[^"]*")/) {
$word = $1;
} elsif (m/\b(?:sprot)\s+("[^"]*")/) {
$word = $1;
};
if ($word) {
s/\bgene_id\s+(?:"[^"]*")/gene_id $word/
};
print;
}
또는 루프를 사용하여 일치하는 키워드를 반복하도록 작성할 수 있습니다.
#!/usr/bin/perl
while (<>) {
my $word = '';
foreach my $match (qw(gene product sprot)) {
if (m/\b(?:$match)\s+("[^"]*")/) {
$word = $1;
last; # first match wins, exit this loop
}
};
if ($word) {
s/\bgene_id\s+(?:"[^"]*")/gene_id $word/
};
print;
}
IMO, 이 버전은 읽고 이해하기가 더 쉽기 때문에 더 좋습니다(특히 루프는 foreach
단어 목록을 반복하는 것에 대해 강조합니다). 게다가 $word = $1
명령문을 반복하지 않아도 됩니다. 명령문을 변경하거나 추가 코드를 추가해야 하는 경우 세 번이 아닌 한 번만 수행하면 실수할 가능성이 줄어듭니다. "반복하지 마세요"는 이와 같은 소규모 프로그램에서는 그다지 중요하지 않지만, 대규모 프로그램에서는 매우 중요할 수 있습니다. 그럼에도 불구하고 중복을 피하거나 최소화하는 것은 좋은 프로그래밍 습관입니다.
일치하는 순서가 중요하지 않은 경우(예: 어느 항목이 검색되는지 상관하지 않으면 해당 항목만 검색됨) 스크립트를 단순화할 수 있습니다.
#!/usr/bin/perl
while (<>) {
my ($word) = m/\b(?:gene|product|sprot)\s+("[^"]*")/;
if ($word) {
s/\bgene_id\s+(?:"[^"]*")/gene_id $word/
};
print;
}
사용하는 스크립트의 버전에 관계없이 이를 다음과 같이 저장 replace.pl
하고 실행 가능하게 만드세요 chmod +x replace.pl
. 아니면 모두 replace1.pl
, replace2.pl
, 로 시도해 보세요 replace3.pl
. 그런 다음 다음과 같이 실행하십시오.
$ ./replace.pl input.txt
chrM Gnomon CDS 8345 8513 . + 1 gene_id "semaphorin-3F"; transcript_id "cds-XP_008824843.3"; Parent "rna-XM_008826621.3"; Dbxref "GeneID:103728653_Genbank:XP_008824843.3"; Name "XP_008824843.3"; end_range "8513,."; gbkey "CDS"; gene "semaphorin-3F"; partial "true"; product "semaphorin-3F"; protein_id "XP_008824843.3"; sprot "sp|Q13275|SEM3F_HUMAN";
chrM StringTie exon 2754 3700 . + . gene_id "ND1"; transcript_id "cds-YP_007626758.1"; Parent "gene-ND1"; Dbxref "Genbank:YP_007626758.1,Gene "ID:15088436"; Name "YP_007626758.1"; Note "TAAstopcodoniscompletedbytheadditionof3'AresiduestothemRNA"; gbkey "CDS"; gene "ND1"; product "NADHdehydrogenasesubunit1"; protein_id "YP_007626758.1"; transl_except "(pos:3700..3700%2Caa:TERM)"; transl_table "2";
답변2
우리는 주어진 키에 여러 값이 적용되면 마지막 값이 최종 값이 되는 해싱의 속성을 활용합니다.
perl -lpe 'my($l,%h)=($_);
$h{gene_id}=$_ for map {
$l =~ /\b$_\s+(".*?");/
} reverse qw(gene product sprot);
s/\bgene_id\s+\K".*?";/$h{gene_id};/;
' your_file_genes
명령은 모두 동일하고 이름만 변경되므로 필드 이름만 제공하고 for 루프가 나머지를 처리하는 전체 작업 시트를 쉽게 구동할 수 있습니다.
for i in gene product sprot;do
cat - <<\_FMT_ |\
sed -e "s/%s/$i/"
s/(\<gene_id\s+)"[^"]*"(.*\s%s\s+("[^"]*"))/\1\3\2/;t
_FMT_
done | sed -Ef - your_file_genes
답변3
솔루션을 완료하려면 perl
다음을 사용하십시오 sed
. 주어진 구문이 어떻게 작동할지 잘 모르겠지만 실제로는 문자열과 일치하는 정규식이 필요합니다.
... gene_id "remove me" ... some other stuff gene "replacement" ... more stuff
======= ====
gene_id "[^"]*" .* gene "[^"]*"
gene_id
그리고 gene
그것은 그 자체로 일치합니다. 큰따옴표로 묶인 문자열은 [^"]*
큰따옴표, 큰따옴표가 아닌 문자( ) 및 다른 큰따옴표를 연결한 것입니다. 마지막으로 당신 사이에 뭔가가 있습니다.*
\(\)
이제 교체품에 재활용해야 하는 부품을 배치 해야 합니다 .
sed 's/gene_id "[^"]*"\(.* gene \("[^"]*"\)\)/gene_id \2\1/'
외부 쌍은 동일하게 유지되어야 하는 모든 것을 포함합니다. 이는 \1
교체용으로 재사용할 수 있습니다. 내부 쌍은 재사용하려는 문자열입니다 gene_id
.
product
이제 또는 대체 대체품으로 사용하려는 경우 sprot
확장 정규식의 대체 문자열을 사용할 수 있습니다.
sed -E 's/gene_id "[^"]*"(.*(gene|product|sprot) ("[^"]*"))/gene_id \3\1/'
그러나 이는 over 를 선호하지 않으며 gene
, 존재하는 마지막 항목을 선호합니다. 해당 우선순위를 얻으려면 별도의 단계가 필요하며 마지막 단계부터 시작하여 더 나은 단계로 바꿀 수 있습니다.product
sprot
sed 's/gene_id "[^"]*"\(.* sprot \("[^"]*"\)\)/gene_id \2\1/
s/gene_id "[^"]*"\(.* product \("[^"]*"\)\)/gene_id \2\1/
s/gene_id "[^"]*"\(.* gene \("[^"]*"\)\)/gene_id \2\1/'
gene
또는 sprot`의 순서가 product
고정되어 있는 것으로 알려진 경우 실제 행을 예약된 공간에 주차하면서 선호하는 ID를 먼저 추출할 수 있습니다.
sed -E 'h;s/(sprot|product|gene) ("[^"]*").*/#\2/;s/.*#//;G;s/(.*)\n(.*gene_id )"[^"]*"/\2\1/'
태그는 #
ID의 일부로 알려지지 않은 문자열일 수 있습니다. GNU의 경우 sed
이를 사용하여 \n
확인할 수 있습니다. 따라서 위 문자열의 첫 번째 줄을 토큰으로 바꾸고 나머지 줄을 삭제한 다음 토큰 앞의 모든 항목을 삭제하면 이제 패턴 공간에는 ID만 남게 됩니다. 그런 다음 G
원래 줄(보유 버퍼에 유지하는 데 사용 ) 이 추가되고 그 뒤에 오는 내용이 h
ID(개행 앞 부분)로 대체됩니다 . 어쩐지 설명하는 것보다 쓰는 것이 더 쉽습니다."string"
gene_id