파일 구문 분석을 위한 awk 명령

파일 구문 분석을 위한 awk 명령

다음 텍스트 파일이 있습니다. 처음 3개 행을 보여드리겠습니다.

chrom   st  end gene    strand  c1  c2  c3  c4  c5  c6  c7  c8  c9  c10 c11 c12 c13 c14
chr6    3345    3543    geneA   +   36  -23 -1  3   1250    946 416 458 475 417 58  80  2   14
chr9    1302    1389    geneB   -   8   -10 -18 -8  2896    2128    635 955 372 385 -20 31  -7  -7

첫 번째 행은 헤더 행이므로 그대로 인쇄하고 싶습니다.

그런 다음 후속 행(즉, 행 2부터 시작)에 대해 처음 5개 필드를 있는 그대로(체인 정보까지) 인쇄하고 그 후에 해당 필드의 값(필드 6에서 시작)이 >= 100이면 값을 인쇄하려고 합니다. 있는 그대로 필드 값이 < 100인 경우 NA로 바꾸면 됩니다.

따라서 내 출력 파일은 다음과 같아야 합니다(이상적으로는 탭으로 구분됨).

chrom   st  end gene    strand  c1  c2  c3  c4  c5  c6  c7  c8  c9  c10 c11 c12 c13 c14
chr6    3345    3543    geneA   +   NA  NA  NA  NA  1250    946 416 458 475 417 NA  NA  NA  NA
chr9    1302    1389    geneB   -   NA  NA  NA  NA  2896    2128    635 955 372 385 NA  NA  NA  NA

답변1

awk 'NR > 1 { for (i = 6; i <= NF; i++) if ($i < 100) $i = "NA" }; 1' yourfile.txt

확장된 코멘트:

NR > 1 {                         # skipping NR == 1, the first line
    for (i = 6; i <= NF; i++)    # column 6 to the end, skipping first 5
        if ($i < 100) $i = "NA"  # self-explanatory
}

1 # print all lines; 1 evaluates to true, and default action is print

편집: 이를 설정하는 방법에는 여러 가지가 있습니다 OFS. 내가 생각할 수 있는 가장 깔끔한 방법은 OFS='\t'파일 이름을 앞에 붙이는 것입니다.

awk '...' OFS='\t' file.txt
awk -v OFS='\t' '...' file.txt
awk 'BEGIN { OFS="\t" }; ...' file.txt

답변2

jw013은 이미 좋은 awk 솔루션을 제공했지만 Perl을 언급한 이후:

perl -lane 'map{$_="NA" if $_<100}@F[5..$#F] if $.>1; print join "\t", "@F"' file 

설명하다

  • perl -lane: 각 입력 라인을 처리하고( -n) 공백으로 배열 @F( -a)로 분할한 후 지정된 스크립트를 실행합니다 -e. 각 줄에서 후행 줄 바꿈을 제거하고 -l각 문에 추가합니다.\nprint

  • map{$_="NA" if $_<100}@F[5..$#F]: @F 배열의 6번째부터 끝까지의 각 요소(필드)가 100 미만인 경우 해당 요소를 "NA"로 변경합니다.

  • if $.>1;: 앞의 내용은 map{}첫 번째 줄이 아닌 경우에만 실행됩니다.

  • print join "\t", "@F"': @F탭을 사용하여 배열의 각 요소를 연결하고(jw013의 답변에 대한 설명에서 요청) 인쇄합니다.

답변3

sed '1n;s|$| |;:na
    s|\([+-] .*\) [+-]*[0-9]\{1,2\} |\1 NA |
    t na;s| $||'

귀하가 보여주신 데이터를 sed s///;t보면 이 작은 기능이 작동하지 않을 이유가 없습니다.(제가 놓쳤을 수도 있는 마지막 칼럼을 지적해주신 jw013님께 감사드립니다.)이는 더 이상 대체할 내용이 없을 때까지 +/-한 줄에서 a 뒤의 모든 1~2자리 숫자 문자열을 그 앞의 모든 문자열로 대체합니다.NA

sed다음은 재귀가 없는 기존 공간을 활용하는 또 다른 버전입니다 h.

sed '1n;h;s|.*[+-] ||;s|$| |
    s| [+-]*[0-9]\{1,2\} | NA |g
    x;G;s|\([+-] *\).*\n|\1|;s| $||'

이는 동일한 마커와 분할 선에 의존합니다. 전반부는 h이전 공간에서 변경되지 않고 그대로 유지되는 반면 패턴 공간에서는 완전히 제거됩니다. 그런 다음 1,2개의 숫자 단어를 모두 전역적으로 바꾸고, h이전 공백에 추가하고, 패턴과 이전 공백을 변경 하고, x추가 작업의 결과로 삽입된 h태그와 ewline 사이의 모든 항목을 제거합니다.\n

관련 정보