コマンドラインでフィールドベースのデータを操作する方法は?例えば
- N番目のフィールドを持つ行のみを印刷する方法は
foo
? - N番目のフィールドではなく行のみを印刷する方法は
foo
? - N番目のフィールドが一致する行だけを印刷する方法は
foo
? - Nフィールドをにどのように変更しますか
foo
?
*nixシステムでフィールドベースのデータを操作するのに役立つ標準的な方法論またはツールセットはありますか?
答え1
フィールドを操作するときに使用できる2つの基本的なアプローチは次のとおりです。 i) フィールドを理解するためのツールの使用 ii) 正規表現の使用。両者の電子は一般的により強力で簡単である。
*nixの多くの一般的なツールには、フィールドを処理するように明示的に設計されているか、またはそれを容易にする賢いトリックがあります。
1. 分野を理解するツールを使う
1.1アーク
ここの古典的なツールは、awk
各入力行を自動的にフィールドに分割し(フィールド区切り文字はデフォルトでは空白ですが、フラグを使用して変更できます)、以下のように-F
これらのフィールドをスクリプトで使用できます。awk
$n
n
フィールド番号です。最初のフィールドはで$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パール
別のオプションはperl
1行です。 awkと同様に、Perlはフル機能のスクリプト言語ですが、スクリプトを入力として使用してコマンドラインプログラムとして実行することもできます。動作はコマンドラインスイッチで変更され、この質問に最も関連するスイッチは次のとおりです。
-e
perl
:実行する必要があるスクリプトです。-n
:入力ファイルを1行ずつ読みます。-p
:Apply;与えられたスクリプトの後に各入力行を印刷します-e
。-l
print
:各入力行から末尾の改行を削除し、各呼び出しに改行を追加します。-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