을 사용하여 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$
나는 알고 싶다,
- 여기서 무슨 일이 일어나고 있는 걸까요?
gunzip -c foo.V2.gz | head
이제 그 말을 믿을 수 있을까gunzip -c foo.V2.gz | head | cat -A
?- 다음을 사용하여 예상 출력을 얻는 방법
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
대신 awk
2가지 유형의 tsv를 지원하고 레코드 구분 기호를 지정할 수 있습니다.
- 값은 ab 로 구분되지만,
--tsv
v
, , 를 사용하여 필드에 TAB, CR 및 LF 문자를 삽입 할 수 있습니다 .t
s
\\
\t
\r
\n
\
- 값은 ab 로 구분
--tsvlite
v
되며 , 필드 값에 줄 구분 기호나 탭 문자를 삽입할 수 없습니다.t
s
여기서는 제목과 값에 이러한 문자가 전혀 포함되지 않은 추가 열을 추가하려고 하므로 그 중 하나를 사용해도 아무런 영향을 미치지 않습니다.
기본적으로 mlr
CRLF(Microsoft) 또는 LF(Unix) 줄 구분 기호가 허용되며 LF(Unix)로 구분된 줄이 출력됩니다. 그러나 --rs crlf
CRLF(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부터 mlr
gzip 압축 파일 읽기 기능이 내장되어 있으므로 다음과 같은 작업도 수행할 수 있습니다.
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이 부적절합니다.이것은 나에게 버그처럼 들린다.