この行は、最初の列に基づいてファイルを縮小します。
awk '{if($1==x){i=i" "$2}else{if(NR>1){print i};i=$0};x=$1;y=$2}' test.cov <(echo)
入力する:
1001 hisk01
1001 hisk02
1001 hisk03
1002 hisk04
1002 hisk05
1002 hisk06
1003 hisk07
1003 hisk08
出力:
1001 hisk01 hisk02 hisk03
1002 hisk04 hisk05 hisk06
1003 hisk07 hisk08
<(echo)
うまくいきますが、ここではどのように機能するのかわかりません。誰でも私を助けることができますか?
ありがとう
答え1
<(
GNU Bourne-Again Shell(Bash)の機能である「プロセス交換」です。 POSIXにはありません。
プロセス置換は、コマンドライン引数に拡張される構文です。ターゲットプログラムは、パラメータをファイル名のように開くことができます。結果ファイル記述子は、括弧の間の構文に示されているコマンドパイプラインに接続されます。
言い換えれば、<(echo)
と同じ単語に展開されます/magic/path/53
。プログラムはこのパスを受け取り、入力ファイルとして開くと読み取るパイプ記述子を取得しますecho
。
echo
効果は何ですか?空行が生成されます。
唯一の違いは
some-command <(echo)
そして
some-command /dev/null
<(echo)
空行だけが生成され、何も生成されませ/dev/null
ん。
空行を含むファイルのパス名であると仮定できます<(echo)
(パス名が出力ではなく入力用にのみ開かれている場合)。
ここでのアイデアは、入力に終了空の行がawk
含まれていることを確認するようです。つまり、入力ファイルに何があっても、空白行test.cov
が追加されます。連続した行間の状態を維持するため、スクリプトのロジックに必要です。i
内容は前の行によって異なり、次の行が到着すると印刷される変数があります。最後の行について計算された内容はi
印刷されないため、余分な空行がなければ、最後の行は完全には処理されません<(echo)
。test.cov
test.cov
終了改行文字が欠落している場合<(echo)
は、単に提供されません。 awk の複数の入力ファイルは単に一緒にリンクされ、単一文字ストリームを形成しません。改行文字の有無にかかわらず、最初のファイルの末尾でレコードが区切られ、2 番目のファイルに対して新しいレコードが生成されます。
周辺シェルからプロセス交換機能への依存関係を削除する簡単な方法があります。
awk '{if($1==x){i=i" "$2}else{if(NR>1){print i};i=$0};x=$1;y=$2}; END {print i}'
それだけです!END
累積レコードを印刷するためのブロックを追加します。 ifは、処理されたレコードがないため定義されていないことを意味し、空の値を印刷するため、テストするi
必要はありません。ただし、この場合は空白行が出力され、使用するとこれを防ぐことができます。NR > 1
NR == 0
i
END {if (i) print i}
答え2
i
これにより、変数内のバッファの最後の内容のみが出力されます。これにより空行が生成されるため、awkはその空行を再度実行して変数にバッファリングさi
れた値を印刷します。代わりに<(echo)
そのブロックを使用できますEND{ print i }
。
また、見ることができます私の答え入力がソート/ソートされていない両方の場合、他の方法でこれを行うにはどうすればよいですか?
答え3
あなたが要求した質問に対する答えを得ましたが、参考にしたいことをする最も一般的な方法の1つは次のとおりです。
$ awk -v ORS= '$1!=prev{print rec; ORS=RS; rec=prev=$1} {rec=rec OFS $2} END{print rec}' file
1001 hisk01 hisk02 hisk03
1002 hisk04 hisk05 hisk06
1003 hisk07 hisk08