コマンドラインからフィールドベースのデータを操作するにはどうすればよいですか?例
- N番目のフィールドが
fooである行のみを印刷するにはどうすればよいですか。 ? - N番目のフィールドが
fooではない行のみを印刷するにはどうすればよいですか。 ? - N番目のフィールドが
fooと一致する行のみを印刷するにはどうすればよいですか。 ? - フィールドNを
fooに変更するにはどうすればよいですか。 ?
* nixシステムでフィールドベースのデータを操作するのを容易にする標準的なアプローチまたはツールセットはありますか?
承認された回答:
フィールドを処理するときに使用できる基本的なアプローチは2つあります。i)フィールドを理解するツールを使用する。 ii)正規表現を使用します。 2つのうち、前者は通常、より堅牢でシンプルです。
* nixで一般的に利用可能なツールの多くは、フィールドを処理するように明示的に設計されているか、フィールドを容易にするための巧妙なトリックを備えています。
1。フィールドを理解するツールを使用する
1.1 awk
ここでの古典的なツールはawkです 。各入力行が自動的にフィールドに分割されます(フィールド区切り文字はデフォルトでは空白ですが、 -Fを使用して変更できます。 フラグ)、フィールドは awkで使用できます $ nとしてのスクリプト ここで、 n フィールド番号です。最初のフィールドは$1です 、2番目の $ 2 など
-
3番目のフィールドが
fooである行を印刷します 。awk '$3=="foo"' file区切り文字を
:に変更しますawk -F":" '$3=="foo"' fileawkのデフォルトのアクション 印刷することです。したがって、上記のコマンドは、3番目のフィールドがfooであるすべての行を出力します。 。-Fを使用する場合 、任意のフィールドセパレータを設定でき、正規表現を使用することもできます。 -
3番目のフィールドが
fooではない行のみを印刷するにはどうすればよいですか。 ?awk '$3!="foo"' file -
3番目のフィールドが
fooと一致する行のみを印刷するにはどうすればよいですか。 ?パターンに一致するフィールドを探しているだけの場合(たとえば、
foofoobarに一致します )、〜を使用します==の代わりに :awk '$3~/foo/' file -
3番目のフィールドが
fooと一致しない行のみを印刷するにはどうすればよいですか。 ?awk '$3!~/foo/' file -
3番目のフィールドを
fooに変更するにはどうすればよいですか。 ?awk '$3="foo"' file
1.2 Perl
もう1つの選択肢はperlです ワンライナー。 awkと同様に、Perlはフル機能のスクリプト言語ですが、スクリプトを入力として受け取るコマンドラインプログラムとして実行することもできます。その動作はコマンドラインスイッチによって変更されます。この質問に最も関連するのは次のとおりです。
-
-e:perlのスクリプト 実行する必要があります; -
-n:入力ファイルを1行ずつ読み取ります; -
-p:-eで指定されたスクリプトを適用した後、各入力行を出力します; -
-l </ code> :各入力行から末尾の改行を削除し、各printに改行を追加します 電話; -
-a:awk-mode、各入力行を配列@Fに分割します; -
-F:-aのフィールドセパレータ 。
awkとの重要な違い そのperl の-a スイッチはファイルを配列に分割します。 Perlでは、配列は1ではなく0から始まります。これは、2番目のフィールドが実際には $ 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"' fileawkとは異なり 、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」)を使用することです。たとえば、フィールドが:で区切られているファイルの場合 、1番目の:までのすべてを照合することで、2番目のフィールドを見つけることができます。 (最初のフィールド)次に2番目のフィールドを探します:
^[^:]*:[^:]*:
この正規表現の意味:
-
^:行の先頭; -
[^]:否定された文字クラス。[^:]「以外のもの:」を意味します 「; -
*:前のパターンの0以上; -
:コード> :リテラル:;
まとめると、これは最初の [^:] *を意味します は最初のフィールドで、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