特定の列に特定の値を持つ行をgrepする方法は?


9

次のようなファイルがあります

  200.000    1.353    0.086
  200.250    1.417    0.000
  200.500    1.359    0.091
  200.750    1.423    0.000
  201.000    1.365    0.093
  201.250    1.427    0.000
  201.500    1.373    0.093
  201.750    1.432    0.000
  202.000    1.383    0.091
  202.250    1.435    0.000
  202.500    1.392    0.087
  202.750    1.436    0.000
  203.000    1.402    0.081
  203.250    1.437    0.001
  203.500    1.412    0.073
  204.000    1.423    0.065
  204.500    1.432    0.055
  205.000    1.441    0.045  

最初の列に10進数の.000と.500のみが含まれる行のみをgrepしたいので、出力は次のようになります。

  200.000    1.353    0.086
  200.500    1.359    0.091
  201.000    1.365    0.093
  201.500    1.373    0.093
  202.000    1.383    0.091
  202.500    1.392    0.087
  203.000    1.402    0.081
  203.500    1.412    0.073
  204.000    1.423    0.065
  204.500    1.432    0.055
  205.000    1.441    0.045  

2
簡単そうですね。これまでに何を試しましたか?コードにはどのような問題がありましたか?
John1024

簡単かもしれませんが、grep '.000'を試してみました| grep '.005'ですが、他の列と同じ値を持つ行もソートされます
Mohsen El-Tahawy

3
とても良い。あなたが問題を自分で解決しようとする正直な試みを示すならば、ここの人々ははるかに同情的です。コメント内のコードはそれを示しています。将来的には、そのような試みを質問に含めると、より速くより良い応答が得られる可能性があります。
John1024 2016年

回答:


14

あなたはgrepを使いません。を使用しawkます。

"your data" | awk '$1 ~ /\.[05]00/'

とても良い。書かれているように、コードは小数点以下3桁に依存しています。使用する方が堅牢awk '$1 ~ /\.[05]0*$/'です。
John1024

1
@ John1024、実際に記述されたコードは、10進数の後に少なくとも 3桁あることに依存します。awk '$1 ~ /\.[05]00$/'可変小数点位置が入力で期待されると考える理由がない限り、私は(自分自身に正確に3桁が必要です)に傾くでしょう。
ワイルドカード

2
@ワイルドカード3つ以上ある場合、コードは失敗する可能性があります。次に例を示しますecho 0.5001 | awk '$1 ~ /\.[05]00/'正確に 3つある場合にのみ確実に機能します。
John1024

4
awk '$1 ~ /\.[50]00/ { print $0 }' myFile.txt

最初の列$1/\.500|\.000/ドットと照合され、~部分的に一致する文字を正規表現ではなく文字どおりのドットにエスケープして、行全体を印刷します。$0


2
含める理由はありません{ print $0 }。これがAwkのデフォルトのアクションです。
ワイルドカード'31年

4

最初の列に10進数の.000と.500がある行のみをgrepしたい

私の最初の考え

grep '^ *[0-9][0-9][0-9]\.[50]00' filename

WSLを使用したクイックテスト

$ head testdata
              200.000    1.353    0.086
              200.250    1.417    0.000
              200.500    1.359    0.091
              200.750    1.423    0.000
              201.000    1.365    0.093
              201.250    1.427    0.000
              201.500    1.373    0.093
              201.750    1.432    0.000
              202.000    1.383    0.091
              202.250    1.435    0.000
$ grep '^ *[0-9][0-9][0-9]\.[50]00' testdata
              200.000    1.353    0.086
              200.500    1.359    0.091
              201.000    1.365    0.093
              201.500    1.373    0.093
              202.000    1.383    0.091
              202.500    1.392    0.087
              203.000    1.402    0.081
              203.500    1.412    0.073
              204.000    1.423    0.065
              204.500    1.432    0.055
              205.000    1.441    0.045

これを表現するより簡潔な方法があります。

$ grep -E '^ *[0-9]{3}\.[50]00' testdata
              200.000    1.353    0.086
              200.500    1.359    0.091
              201.000    1.365    0.093
              201.500    1.373    0.093
              202.000    1.383    0.091
              202.500    1.392    0.087
              203.000    1.402    0.081
              203.500    1.412    0.073
              204.000    1.423    0.065
              204.500    1.432    0.055
              205.000    1.441    0.045

最初の列に3桁以外の整数部分がある場合

grep -E '^ *[0-9]+\.[05]00' testdata

状況によっては[:digit:]、の代わりに使用する必要がある場合があります[0-9]

等々。

man grep あなたの友だちです。


この使用法はgrep私のものよりも使いやすいです。これを最初に見たとしたら、私は答えを投稿しなかっただろう。良くやった!
妖怪

2

ユースケースによっては、実際の数値演算を使用することもあります。

$ awk '{a = $1 % 1} a == 0 || a == 0.5' /tmp/foo
  200.000    1.353    0.086
  200.500    1.359    0.091
  201.000    1.365    0.093
  201.500    1.373    0.093
  202.000    1.383    0.091
  202.500    1.392    0.087
  203.000    1.402    0.081
  203.500    1.412    0.073
  204.000    1.423    0.065
  204.500    1.432    0.055
  205.000    1.441    0.045

BSD awk(OSX El Capitan、20070501)およびGNU awk 4.1.4でテスト済み。


1
警告:浮動小数点(awkが使用する)の正確な等価性をテストすると、値に小数部がない(および大きさが大きすぎない)か、小数部が「バイナリ」(正確に半分、四半期など)これは、このQのデータには当てはまりますが、初心者に似ている他の多くのデータには当てはまりません。
dave_thompson_085 2016年

1
@ dave_thompson_085確かに、しかしgawkでは任意の精度の算術演算を使用できます。確かに、ここではそれらを使用していません。
muru、


2

awk

$>awk '$1%.5==0' data.tsv 
200.000 1.353   0.086
200.500 1.359   0.091
201.000 1.365   0.093
201.500 1.373   0.093
202.000 1.383   0.091
202.500 1.392   0.087
203.000 1.402   0.081
203.500 1.412   0.073
204.000 1.423   0.065
204.500 1.432   0.055
205.000 1.441   0.045

mlr

$>mlr --ifs tab --onidx filter '$1%.5==0' data.tsv 
200.000 1.353 0.086
200.500 1.359 0.091
201.000 1.365 0.093
201.500 1.373 0.093
202.000 1.383 0.091
202.500 1.392 0.087
203.000 1.402 0.081
203.500 1.412 0.073
204.000 1.423 0.065
204.500 1.432 0.055
205.000 1.441 0.045

2

OK、少し遅れて私の貢献を追加しましたが、それだけの価値があると思います。

OPごとに満たす必要のある要件は、10進値.000またはそれ.500のみを持つ最初の列です。範囲または長さのどちらでも、先行値についての規定はありません。堅牢性のためには、そこには非空白文字が最初の列の前ではない(または、それはもはや最初の列です)ことを除いては何によって制約されると仮定すべきではないと最初の列の内容があることだろう、小数点を持って.、どこかに。

OPはを使用したいgrepので、一致が見つかると行全体が印刷されます。そのため、唯一必要なことは、すべてと一致するパターンだけを作成することです。

シンプルそのもの、と理由はないに使用するsedawkのように`grepが、ファイルやパイプなどのソースを扱うことができます。

grepファイルの使用grep '^[^.]*\.[05]0\{2\}\s' the_file.txt

grepパイプから、使用my_command | grep '^[^.]*\.[05]0\{2\}\s'

パターンは次のとおり^です。、行の先頭から開始します。[^.]、すべての非小数点文字に一致します。*、できるだけ多く(なしを含む)。\.、小数点に一致します。[05]、5または0のいずれかに一致します。0\{2\}、さらに2つのゼロに一致します(開始および終了の括弧の前のバックスラッシュは、シェルが括弧の拡張を試みないようにします)。\s、空白文字に一致します(列の末尾を意味します-別のユースケースで使用するには、列の区切り文字、通常はコマンド、セミコロン、またはタブで置き換えます\t)。

これは、OPが要求したものと正確に一致することに注意してください。それはなりません一致する.5000.0000を正確に続いて5またはゼロ、のためのパターンルックスので、同等の数値にもかかわらず、2以上のゼロは空白が続きます。それが重要である場合、これまでの他のすべての回答は、テストディジットの後に、1より大きいゼロの任意の数と一致するという点で失敗します。そしてFloHimselfによって答えを除いて、彼らが一致するものを 2列目に始まる .000.500、など、.0003.500T、とFloHimselfずつは数学的に等価であるものと一致します.0し、.5、ゼロがいくつあっても。最後のものは、OPが述べたものと一致しませんが、いずれにしてもOPが必要とするものと一致する可能性があります。

最後に、awkOPがを要求した場合でも、のパワーと速度が必要な場合、grepコマンドは次のようになります。

ファイル付き awk '$1 ~ /[^.]\.[05]0{2}$/' the_file.txt

パイプ付き my_command | awk '$1 ~ /[^.]\.[05]0{2}$/'


1

grepの使用を主張する場合、これでうまくいくかもしれません。提供した最初の出力を "file.txt"というテキストファイルに保存し、次のコマンドを使用しました。

grep -e '2[^ ]*.000' file.txt & grep -e '2[^ ]*.500' file.txt

次の出力が得られます。

200.000    1.353    0.086
200.500    1.359    0.091
201.500    1.373    0.093
201.000    1.365    0.093
202.500    1.392    0.087
202.000    1.383    0.091
203.500    1.412    0.073
203.000    1.402    0.081
204.500    1.432    0.055
204.000    1.423    0.065
205.000    1.441    0.045

既にファイル内にある場合は、出力をテキストファイルに保存する必要はありません。ただし、ファイルに保存されていない場合は、提供したgrepコマンドにデータをパイプすることもできます。少なくとも2、最初の列の最初の数字がでなくなるまで、データは機能し2ます。その時点で、正しく印刷するには、適切な文字でgrepコマンドを更新する必要があります。

このデュアルgrepコマンドで起こっていることは、最初のコマンドがオペレーターgrepと一緒にバックグラウンドに送信されていること&です。バックグラウンドに送信されると、次のgrepコマンドがすぐに実行され、統一された出力が得られます。完了しなければならないタスクをより簡単に実行するには、他の人が与えて使用した例を使用するawk必要がありsedます。

(編集)

これは決してあなたのニーズに合ったgrepの最良または最も効果的な使用法ではありませんが、少し遊んでgrepをよりよく感じるには十分なはずです。


最初のプロセスはバックグラウンドで実行されますが、バックグラウンドでの実行を含むデーモン化さていませんが、かなり多くのプロセスがあります。そして、入力と同じ順序で出力を生成することはほとんどありません。非常に小さな例でも、3行目ですでに問題が発生しています。
dave_thompson_085

彼は、出力が特定の順序である必要があることについては言及していません。最初の列の.500and .000に固有である必要があることのみ。それが特定の順序である必要がある場合(最低から最高など)は、簡単に実行できます。ただし、印刷される最初の列の最初の3桁は、少なくとも大きい順です。それはの結果である2[^ ]*.0002[^ ]*.500。それはOPが要求したものにかなり適合しています。
妖怪、

また、提供したコマンドの効率に関する免責事項の編集にも注意してください。
妖怪
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.