を使用して、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が不適切です。これは私にバグのように聞こえます。