각 열의 행에서 부분 문자열 추출

각 열의 행에서 부분 문자열 추출

다음과 같이 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

awkPOSIX 정의 구조에만 사용됩니다.

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
  • 이 방법은 개별 필드 사이에 존재하는 간격을 방해하지 않습니다. 이것은 중요할 수도 있고 중요하지 않을 수도 있습니다.
  • 참고: 참고: 네 번째 필드에 유전자가 있다고 가정합니다. 여러 유전자의 경우 오류나 경고를 표시하지 않고 기록의 네 번째 필드에 있는 마지막 유전자를 자동으로 선택합니다.

관련 정보