다음과 같이 20,000줄이 넘는 텍스트 파일이 있습니다.
7 128550681 128550681 Intron:1:36:RETAINED-RETAINED;Transcript:NM_001135914.1;Gene:KCP:protein_coding 1 1 0 0
1 17718672 17718672 Intron:9:16:RETAINED-RETAINED;Transcript:NM_207421.4;Gene:PADI6:protein_coding 1 1 0 0
1 17718672 17718672 Intron:9:16:RETAINED-RETAINED;Transcript:NM_207421.4;Gene:PADI6:protein_coding 1 1 0 0
4 86035 86035 Exon:4:5:RETAINED;Transcript:NM_001286052.1;Gene:ZNF595:protein_coding 1 1 0 0
3 12942851 12942851 Intron:14:14:SKIPPED-ALTTENATIVE_3SS;Transcript:NM_001134382.2;Gene:IQSEC1:protein_coding 1 1 0 0
필요한 것은 네 번째 열에 Gene:genename만 포함되어 있으므로 출력은 다음과 같습니다.
7 128550681 128550681 Gene:KCP 1 1 0 0
1 17718672 17718672 Gene:PADI6 1 1 0 0
1 17718672 17718672 Gene:PADI6 1 1 0 0
4 86035 86035 Gene:ZNF595 1 1 0 0
3 12942851 12942851 Gene:IQSEC1 1 1 0 0
Gene:genename
* :
누르거나 분할하려고 할 때 문제가 항상 같은 위치에 나타나지는 않습니다.;
나는 특정 열을 선택하는 방법, 특정 패턴이 포함된 줄을 찾는 방법과 같은 매우 기본적인 awk/sed를 알고 있습니다.
답변1
awk
다음 명령을 사용하여 이 작업을 수행 할 수 있었습니다 .
awk '{sub(/^.*;/,"",$4); print}' input
이렇게 하면 마지막 항목까지 4열의 모든 내용이 삭제되며 ;
이는 작동하지 않을 수 있습니다(Steeldriver의 설명 참조). 이 경우 명확한 설명을 포함하여 질문을 업데이트하세요.
답변2
awk
POSIX 정의 구조에만 사용됩니다.
awk 'match($4, /Gene:(.+)\:/){ $4=substr($4, RSTART, RLENGTH-1) }1' file
출력을 더욱 깔끔하게 정렬하려면 출력을 | column -t
탭으로 구분된 열에 파이프하세요. 위치가 확실하지 않은 경우 패턴을 Gene:genename
변경하여 awk
행의 아무 곳이나 찾고 네 번째 열을 원하는 값으로 수정하세요. $4
( 전체 라인) 으로 변경하면 $0
정상적으로 작동합니다.
awk 'match($0, /Gene:(.+)\:/){ $4=substr($0, RSTART, RLENGTH-1) }1' file
답변3
perl -pale 's#(?:\H+\h+){3}\K\H+#($F[3] =~ /(?:^|;)(Gene:[^:]+)/)[0]#e' input-file.txt
° 네 번째 필드의 유전자 위치가 고정되어 있지 않은 경우 위와 같이 동작할 수 있습니다.
° 정규식을 통해 네 번째 필드를 0으로 만들고 (?:\H+\h+){3}\K\H+
명령 대체 섹션에서 사용되는 다른 정규식으로 즉시 대체합니다 s///e
.
답변4
진주:
perl -F'\h+' -lane '
for ( $F[3] ) {
my $a = index(";$_", ";Gene:" );
my $b = index(";$_", ":", $a+6 );
$_ = substr(";$_", $a+1, $b-$a-1);
}
print join "\t", @F;
' input-file.txt
산출:
7 128550681 128550681 Gene:KCP 1 1 0 0
1 17718672 17718672 Gene:PADI6 1 1 0 0
1 17718672 17718672 Gene:PADI6 1 1 0 0
4 86035 86035 Gene:ZNF595 1 1 0 0
3 12942851 12942851 Gene:IQSEC1 1 1 0 0
$ 128550681 128550681 Gene:$$$ 1 1 0 0
설명하다:
perl
옵션:-n
=> 입력 내용을 한 줄씩 읽도록 호출합니다.-F
=> 만들겠습니다FS = horizontal whitespace
.-a
=> 각 행을 필드(-F
옵션 설정에 따른 FS 또는 기본적으로 단일 공백)로 분할하고 배열에 저장합니다@F
.-l
=> 만들겠습니다RS = ORS = "\n"
.-e
=> 다음 내용은Perl
코드로 처리되어 모든 줄, 즉 레코드에 적용됩니다.
data structures
관련:@F
=> 레코드를 분할하여 얻은 필드로 채워진 배열입니다. 인덱싱은 0부터 시작됩니다.$F[3]
레코드의 네 번째 필드에도 마찬가지입니다.$a
;Gene:
=> 네 번째 필드에 하위 문자열의 위치를 저장합니다.$b
=> 하위 문자열의 위치를 4번째 필드에 저장하면:
해당 위치 이후 6자리를 찾을 수 있습니다;Gene:
. IOW,:
그 다음으로 두 번째를 찾았습니다;Gene
. 참고: 검색 문자열에 세미콜론을 채웁니다. 즉,$F[3]
위치는Gene:
어디에나 있을 수 있으므로 네 번째 필드의 시작 부분에도 있을 수 있습니다. 이는 이러한 가능성에 대처하기 위한 것입니다.$_
$F[3]
=> 루프 내부에 현지화된 버전을 저장합니다for
. 내장된 기능은 정보를substr
추출하여 다시 저장합니다 .gene:...
$F[3]
- 참고:
my
변수 정의 앞의 한정자는$a,$b
이를 범위가 루프로 제한되는 어휘 변수로 표시합니다for
. - 참고: 현재 레코드/행은 루프
$_
내에서 참조되지 않습니다.for
루프 기간for
이$F[3]
.
GNU Sed:
sed -Ee '
s/\S+/\n&\n/4
s/\n(.*;)?(Gene:[^:]+):.*\n/\2/
' input-file.txt
설명하다:
- 네 번째 필드를 개행 문자로 표시합니다.
- 현재 행 의 영역을 측설한 후 필요한 데이터(이 경우)를 찾은 다음
Gene:
.as many non colons we meet on the way before we hit the next colon
- 이 방법은 개별 필드 사이에 존재하는 간격을 방해하지 않습니다. 이것은 중요할 수도 있고 중요하지 않을 수도 있습니다.
- 참고: 참고: 네 번째 필드에 유전자가 있다고 가정합니다. 여러 유전자의 경우 오류나 경고를 표시하지 않고 기록의 네 번째 필드에 있는 마지막 유전자를 자동으로 선택합니다.