データがフィールドで区切られたテキストファイルの行を抽出/変更する方法は?

データがフィールドで区切られたテキストファイルの行を抽出/変更する方法は?

コマンドラインでフィールドベースのデータを操作する方法は?例えば

  • N番目のフィールドを持つ行のみを印刷する方法はfoo
  • N番目のフィールドではなく行のみを印刷する方法はfoo
  • N番目のフィールドが一致する行だけを印刷する方法はfoo
  • Nフィールドをにどのように変更しますかfoo

*nixシステムでフィールドベースのデータを操作するのに役立つ標準的な方法論またはツールセットはありますか?

ベストアンサー1

フィールドを操作するときに使用できる2つの基本的なアプローチは次のとおりです。 i) フィールドを理解するためのツールの使用 ii) 正規表現の使用。両者の電子は一般的により強力で簡単である。

*nixの多くの一般的なツールには、フィールドを処理するように明示的に設計されているか、またはそれを容易にする賢いトリックがあります。

1. 分野を理解するツールを使う

1.1アーク

ここの古典的なツールは、awk各入力行を自動的にフィールドに分割し(フィールド区切り文字はデフォルトでは空白ですが、フラグを使用して変更できます)、以下のように-Fこれらのフィールドをスクリプトで使用できます。awk$nnフィールド番号です。最初のフィールドはで$1、2番目のフィールドは$2このようになります。

  • 3番目のフィールドを含む行を印刷しますfoo

    awk '$3=="foo"' file
    

    区切り文字を次に変更します。:

    awk -F":" '$3=="foo"' file
    

    デフォルトのジョブはawk印刷です。したがって、上記のコマンドは3番目のフィールドを持つすべての行を印刷しますfoo。を使用すると、-Fフィールド区切り文字を設定し、正規表現を使用することもできます。

  • 3番目のフィールドではなく行のみを印刷する方法はfoo

    awk '$3!="foo"' file
    
  • 3番目のフィールドが一致する行のみを印刷する方法はfoo

    fooパターンに一致するフィールド(matchなどfoobar)を探している場合は、~代わりに次を使用してください==

    awk '$3~/foo/' file
    
  • 3番目のフィールドが一致しない行のみを印刷するにはどうすればよいですかfoo

    awk '$3!~/foo/' file
    
  • 3番目のフィールドをにどのように変更しますかfoo

    awk '$3="foo"' file
    

1.2パール

別のオプションはperl1行です。 awkと同様に、Perlはフル機能のスクリプト言語ですが、スクリプトを入力として使用してコマンドラインプログラムとして実行することもできます。動作はコマンドラインスイッチで変更され、この質問に最も関連するスイッチは次のとおりです。

  • -eperl:実行する必要があるスクリプトです。
  • -n:入力ファイルを1行ずつ読みます。
  • -p:Apply;与えられたスクリプトの後に各入力行を印刷します-e
  • -lprint:各入力行から末尾の改行を削除し、各呼び出しに改行を追加します。
  • -a:awk-mode、各入力ラインを配列に分割します@F
  • -F:フィールド区切り記号-a

1つの重要な違いは、スイッチがファイルを配列に分割することawkです。 Perlでは、配列は1ではなく0から始まります。つまり、2番目のフィールドは実際にはありません。これらすべてを考慮すると、上記は次のとおりです。perl-a$F[1]$F[2]perl

  • 3番目のフィールドを含む行を印刷しますfoo

    perl -ane 'print if $F[2] eq "foo"' file
    

    区切り文字を次に変更します。:

    perl -F":" -ane 'print if $F[2] eq "foo"' file
    

    awkとは異なり、perl正規表現はフィールド区切り文字として使用できません。特定の文字または文字列でなければなりません。

  • 3番目のフィールドではなく行のみを印刷する方法はfoo

    perl -ane 'print unless $F[2] eq "foo"' file
    
  • 3番目のフィールドが一致する行のみを印刷する方法はfoo

    perl -ane 'print if $F[2]=~/foo/' file
    
  • 3番目のフィールドが一致しない行のみを印刷するにはどうすればよいですかfoo

    perl -lane 'print unless $F[2]=~/foo/' file
    
  • 3番目のフィールドをにどのように変更しますかfoo

    Perlではこれが少し問題になります。一般的なアプローチは、配列の値を変更して@Fから配列を印刷することです。単純なスペースで区切られたファイルの場合は、次のように簡単です。

    perl -lane '$F[2]="foo"; print "@F"' file
    

    別の区切り文字を使用する場合は配列が必要ですjoin。それ以外の場合は、スペースで区切られて印刷されます。

    perl -F: -lane '$F[2]="foo"; print join ":",@F' file
    

2.正規表現を使用してください

ここでのアイデアは、正規表現(「regex」)を使用して行内のターゲット文字列の位置を定義することです。たとえば、フィールドで区切られたファイル内の:最初のフィールド(最初のフィールド)の前のすべての項目を一致させ、次に2番目のフィールドを見つけて:2番目のフィールドを見つけることができます。

^[^:]*:[^:]*:

この正規表現の意味は次のとおりです。

  • ^:行の始まり。
  • [^]: 不正な文字クラスです。[^:]:以外のもの」を意味します。
  • *:0個以上の古いパターン。
  • ::文字通りの意味:

全体として、これは、第1の[^:]*フィールドが第1のフィールドであり、第2のフィールドが第2のフィールドであることを意味する。明らかに、これは14番目のフィールドを探している場合はあまり実用的ではありませんが、より簡単な作業には便利です。それでは、データを操作するためにこれをどのように実装しますか?これを行うには、さまざまなツールがあります。この例ではを使用しますが、使用するsedか、awk非常perlに似た操作を実行することもできますpython

  • 2番目のフィールドを持つ行のみを印刷するにはどうすればよいですかfoo

    sed -n '/^[^:]*:foo:/p' file
    

    -n通常の出力を抑制します。/regex/pつまり、「正規表現に一致するすべての行を印刷します。

  • 2番目のフィールドではなく行のみを印刷する方法はfoo

    sed '/^[^:]*:foo:/d' file
    

    上記の論理と反対です。ここでは、/regex/d「正規表現に一致するすべての行を削除します」を意味します。

  • 2番目のフィールドが一致する行のみを印刷するにはどうすればよいですかfoo

    sed -n '/^[^:]*:[^:]*foo/p' file
    
  • 2番目のフィールドが一致しない行のみを印刷するにはどうすればよいですかfoo

    sed '/^[^:]*:[^:]*foo/d' file
    
  • 2番目のフィールドをにどのように変更しますかfoo

    sed 's/\([^:]*:\)[^:]*/\1foo/' file 
    

    あるいは、置換はsed単純な数値フラグ反復を使用してパターン発生を直接解決することができるので、次のようになります。

    sed 's/[^:]*/foo/2' file
    

おすすめ記事