awk는 cat -A를 사용하여 표시된 것처럼 .gz 파일에 열을 추가하지만 일반 출력에서 ​​열 이름을 변경합니다.

awk는 cat -A를 사용하여 표시된 것처럼 .gz 파일에 열을 추가하지만 일반 출력에서 ​​열 이름을 변경합니다.

을 사용하여 awk이 테이블에 첫 번째 행이 "INFO"이고 나머지 행이 "1"인 열을 추가하고 싶습니다.

$ gunzip -c foo.gz | head
SNPID   CHR BP  Allele1 Allele2 Freq1   Effect  StdErr  P.value TotalN
rs1000033   1   226580387   t   g   0.8266  -0.0574 0.0348  0.09867 17310
rs1000050   1   162736463   t   c   0.8545  0.0654  0.0461  0.1564  10864

어디

gunzip -c foo.gz | head | cat -A
SNPID^ICHR^IBP^IAllele1^IAllele2^IFreq1^IEffect^IStdErr^IP.value^ITotalN^M$
rs1000033^I1^I226580387^It^Ig^I0.8266^I-0.0574^I0.0348^I0.09867^I17310^M$
rs1000050^I1^I162736463^It^Ic^I0.8545^I0.0654^I0.0461^I0.1564^I10864^M$

.gz제가 사용한 파일 이거든요.

gunzip -c foo.gz | \
  awk 'BEGIN {FS="\t"; OFS="\t"} NR == 1 {print $0 OFS "INFO"} NR > 1 {print $0 OFS "1"}' | \
  gzip > foo.V2.gz

어떤 이유로 이것은 내 열 이름을 변경하는 것 같지만 마지막에 예상되는 열은 변경되지 않습니다.

$ gunzip -c foo.V2.gz | head   
SNPID   INFO    BP  Allele1 Allele2 Freq1   Effect  StdErr  P.value TotalN
--------^
rs1000031   1   226580387   t   g   0.8266  -0.0574 0.0348  0.09867 17310
rs1000051   1   162736463   t   c   0.8545  0.0654  0.0461  0.1564  10864

이상한 점은 cat -A기둥을 보면 원래 있어야 할 곳에 있는 것 같다는 것입니다.

$ gunzip -c foo.V2.gz | head | cat -A                                      
SNPID^ICHR^IBP^IAllele1^IAllele2^IFreq1^IEffect^IStdErr^IP.value^ITotalN^M^IINFO$
----------------------------------------------------------------------------^ 
rs1000033^I1^I226580387^It^Ig^I0.8266^I-0.0574^I0.0348^I0.09867^I17310^M^I1$
rs1000050^I1^I162736463^It^Ic^I0.8545^I0.0654^I0.0461^I0.1564^I10864^M^I1$

나는 알고 싶다,

  1. 여기서 무슨 일이 일어나고 있는 걸까요?
  2. gunzip -c foo.V2.gz | head이제 그 말을 믿을 수 있을까 gunzip -c foo.V2.gz | head | cat -A?
  3. 다음을 사용하여 예상 출력을 얻는 방법gunzip -c foo.V2.gz | head

SNPID   CHR BP  Allele1 Allele2 Freq1   Effect  StdErr  P.value TotalN INFO
rs1000033   1   226580387   t   g   0.8266  -0.0574 0.0348  0.09867 17310 1
rs1000050   1   162736463   t   c   0.8545  0.0654  0.0461  0.1564  10864 1

노트SNPID=1; CHR=2; ..., 나는 내가 지정한 열 번호가 후속 분석을 위해 올바른지 여부에 따라 현재 위치를 정의하기 위해 구성 스크립트를 사용하고 있습니다 .

답변1

이미 언급했듯이 DOS 줄 끝이 있습니다. 바라보다내 도구 출력이 자체적으로 덮어쓰이는 이유와 해결 방법문제 및 가능한 해결 방법에 대한 설명(예: awk 사용):

gunzip -c foo.gz |
  awk -v OFS='\t' '{sub(/\r$/,""); print $0, (NR>1 ? 1 : "INFO")}' |
  gzip > foo.V2.gz

RS="\r\n"최근 1~2개의 다른 awk 변형에 채택된 GNU awk 확장인 다중 문자 RS를 ​​사용할 수 있습니다 . 다른 POSIX 호환 awk 설정은 RS="\r\n"설정한 것과 동일하게 처리됩니다. RS="\r"각 POSIX는 RS단일 리터럴 문자만 될 수 있기 때문입니다. 또한 awk가 보기 전에 기본 C 프리미티브 \r가 줄 끝을 제거하는 시스템에서는 실패하므로 RS="\r?\n"더 강력합니다. awk의 경우 RS기본값으로 두고 스크립트의 첫 번째 명령문으로 \n추가할 수 있습니다.{sub(\r$/,"")}

또한 필요하지 않거나 이미 값이 있는 코드 설정 변수를 제거하고, 2개의 인쇄 문을 1로 변경하고, OFS를 설계된 대로 사용하고, 파이프 기호에서 불필요한 이스케이프를 제거하는 등 스크립트에서 몇 가지 다른 사항도 정리했습니다. 이후 줄 끝.

답변2

입력하신 내용은 Microsoft 줄 끝이 있는 일종의 TSV 파일인 것 같습니다.

그런 다음 사용할 수 있습니다mlr대신 awk2가지 유형의 tsv를 지원하고 레코드 구분 기호를 지정할 수 있습니다.

  1. 값은 ab 로 구분되지만, --tsv v, , 를 사용하여 필드에 TAB, CR 및 LF 문자를 삽입 할 수 있습니다 .ts\\\t\r\n\
  2. 값은 ab 로 구분 --tsvlite v되며 , 필드 값에 줄 구분 기호나 탭 문자를 삽입할 수 없습니다.ts

여기서는 제목과 값에 이러한 문자가 전혀 포함되지 않은 추가 열을 추가하려고 하므로 그 중 하나를 사용해도 아무런 영향을 미치지 않습니다.

기본적으로 mlrCRLF(Microsoft) 또는 LF(Unix) 줄 구분 기호가 허용되며 LF(Unix)로 구분된 줄이 출력됩니다. 그러나 --rs crlfCRLF(Microsoft)로 구분된 출력 라인에 전달할 수 있습니다.

그래서:

< foo.gz gunzip |
  mlr --tsvlite put '$INFO = 1' |
  gzip > foo.V2.gz

출력 시 Unix TSV를 가져오고 입력 시 Microsoft 또는 Unix TSV를 허용합니다.

< foo.gz gunzip |
  mlr --tsvlite --rs crlf put '$INFO = 1' |
  gzip > foo.V2.gz

출력 시 Microsoft TSV를 가져오고 입력 시 Microsoft 또는 Unix TSV를 허용합니다.

버전 6.0.0부터 mlrgzip 압축 파일 읽기 기능이 내장되어 있으므로 다음과 같은 작업도 수행할 수 있습니다.

mlr --tsvlite put '$INFO = 1' foo.gz |
  gzip > foo.V2.gz

--gzin(파일 경로가 로 끝나지 않는 경우 이 옵션이 전달됩니다 .gz.

mlr(밀러,일반적 miller으로 패키지로 배송됩니다.)은 표 형식 데이터 처리에 특화된 도구입니다. 이를 위해서는 일부가 필요할 수 있습니다.동사sort, cut, ... 등 레코드에 대해 다양한 작업을 수행하기 위한 매개 join변수filter

put다음을 사용하여 레코드를 수정하는 데 사용됩니다.단순한도메인 특정 언어상황은 의 경우와 크게 다르지 않습니다 awk.

awk예 를 들어 해당 언어에서는$레코드의 필드를 참조하는 데 사용됩니다.이 필드를 제외하고는명명 된1. 의 경우 $INFO = 1각 레코드의 필드에 INFO숫자² 값을 할당합니다 1. 필드가 아직 존재하지 않으면 해당 필드가 추가되어 추가 열로 표시됩니다.


1 그러나 다음과 같이 사용할 수도 있습니다 --implicit-csv-header.

² $INFO = "1"JSON과 같은 출력 형식에 다른 영향을 미치는 문자열로 설정할 수 있지만 유형 표시가 없는 tsv의 경우에는 그렇지 않습니다.

답변3

~처럼@스틸드라이버설명에서 언급한 대로 파일은 Windows에서 캐리지 리턴(CR) 및 줄 바꿈(LF) 문자로 오염된 것으로 보이며 동일한 문제가 다시 발생 RS="\r\n"하지 않고 설정된 레코드 구분 기호를 제거할 수 있습니다.ORS="\n"

gunzip -c foo.gz | \
  awk 'BEGIN {FS=OFS="\t";RS="\r\n";ORS="\n"} NR == 1 {print $0 OFS "INFO"} NR > 1 {print $0 OFS "1"}' | \
  gzip > foo.V2.gz

답변4

LF(Unix) 또는 CR 뒤에 LF(Microsoft)가 있는지 여부에 관계없이 <tab>INFO줄 구분 기호 앞에 첫 번째 또는 후속 줄을 추가 하려면 다음을 수행할 수 있습니다.<tab>1

<foo.gz gunzip |
  perl -pe 's/(?=\r?$)/$. == 1 ? "\tINFO" : "\t1"/e' |
  gzip > foo.V2.gz

파일을 내부에서 편집하려면 이론적으로 IO 레이어 -i에서 이 옵션을 사용할 수 있어야 합니다(별도 설치가 필요할 수 있음).PerlIO::gzip

perl -Mopen=IO,gzip -i -pe 's/(?=\r?$)/$. == 1 ? "\tINFO" : "\t1"/e' foo.gz

내 버전이 실패했음을 발견했지만foo.gz에서 내부 편집을 수행할 수 없습니다. 임시 이름을 생성할 수 없습니다. 장치에 대한 ioctl이 부적절합니다.이것은 나에게 버그처럼 들린다.

관련 정보