web-dev-qa-db-ja.com

awkまたはsedを使用して複数の列を削除する

6037のスペースで区切られた列と以下のような450行のデータベースがあります。

1807 1452 1598 1 6.655713  A B A B ... 0 
1808 1452 1763 1 9.362033  0 0 A B ... A 
1809 1452 1527 2 6.728534  A B A A ... B 
1810 1452 1367 2 9.4055  A B A A B ... A 
... ... ... ... ... ... ... ... ... ...
1812 1452 1258 1 6.363032  0 0 A B ... B

最初の676列のみの新しいデータベースを取得したいと考えています。

できれば、awkまたはsedコマンドを使用するフォームを使用してください。

4
andrec

ファイルの列区切り文字が1文字の場合、たとえば、スペース、cutはそれを簡単に行うことができます:

_cut -d' ' -f-676 <in >out
_

これは、スペースで区切られた列だけを最初から676番目まで印刷します。

必要な場合区切り文字としてカウントするすべての空白文字、sedソリューションは次のとおりです。

_sed -r 's/\s+\S+//677g' <in >out
_

これは、677番目で始まるすべての列(=少なくとも1つの空白文字の後に少なくとも1つの非空白文字が続く)を何も置き換えません。文字グループを使用すると、必要な区切り文字のセットを指定できます。 「4」、「#」、「K」の場合:

_sed -r 's/[4#K]+[^4#K]+//677g' <in >out
_

reasonableawkアプローチについては、親切に steeldriver's answer を参照してください。ただし、列をループする別の方法があります番号が676以下の場合のみ、それらを(FSで区切って)印刷します

_awk '{for (i=1;i<=676;i++) {printf (i==1?"":FS)$i}; print ""}' <in >out
_

文字グループの場合、出力の出力フィールド区切り文字を指定する必要があります。 _[4#K]_および_"sep"_の場合:

awk -F'[4#K]' '{for (i=1;i<=676;i++) {printf (i==1?"":"sep")$i}; print ""}' <in >out
8
dessert

単一文字の区切り文字(スペースやコンマなど)の場合、cutまたはawkではなくsedコマンドを使用することをお勧めします。

ただし、awkについて具体的に質問したので、I thinkを行う合理的な方法は、フィールドカウントをデクリメントすることです。

awk -v last=676 '{NF = last} 1' datafile

GNU Awk(gawk)およびmawkでテスト済み。

5
steeldriver

あなたは使うことができます

mlr --nidx --fs ' ' --repifs cat inputFile.csv | cut -d ' ' -f-2

この方法でmlr( https://github.com/johnkerl/miller/releases/tag/5.4. )を使用すると、フィールド区切り文字を管理できます(複数のスペースがある場合、それらは1つにつき1つになります)フィールド)、そしてカットを使用して(私の例では)最初の2つのフィールドを抽出します。

から

1807   1452 1598  1 6.655713  A B A B
1808 1452 1763 1  9.362033  0 0 A B
1809 1452 1527 2 6.728534  A B   A A
1810 1452 1367 2 9.4055  A B A A B

1807 1452
1808 1452
1809 1452
1810 1452

ミラーオプションに関する注意事項:

  • --nidxはフォーマットを設定することです。これは一般的なインデックス番号付きテーブルです(最初のフィールドは1、2番目のフィールドは2など)。
  • --fsセパレーターを設定します(ここにスペースがあります)。
  • --repifsは、フィールドセパレーターの連続する複数のオカレンスが1つとしてカウントされることを意味します
  • catは、入力レコードを直接出力に渡します。
3
aborruso