2017-08-16 11 views
2

私はAWKを使用して非常に不満な問題を抱えており、ここで解決策を見つけることができませんでした。 非常に簡単です:AWK:列内の値のインスタンスを検索しようとしています。 awkはNanのインスタンスと値を返す

私は3つの列を含むテキストファイル 'myfile.txt'を持っています。内容は以下のとおりです。

awk '{if ($3 == 3) print $1, $2, $3}' myfile.txt

戻り値:

-101.358 80.775 3 
-98.019 80.976 NaN 
-96.476 81.0566 NaN 

何らかの理由でそれについて

-101.358 80.775 3 
-100.187 80.850 2 
-98.019 80.976 NaN 
-96.476 81.0566 NaN 

私がやりたいことのすべては、列3 = 3だから私はインスタンスを取得でNaNと私が探している3を返しています。

awk '$3 == 3 {print $1, $2, $3}' myfile.txt

戻り値:

-101.358 80.775 3 
-98.019 80.976 NaN 
-96.476 81.0566 NaN 

は私がやって問題を克服することができます

awk '{if ($3 == 3 && $3 != nan) print $1, $2, $3}' myfile.txt

戻り値:

私はと同じ結果を得ます

しかし、awkを使用してファイル内の値のインスタンスを見つけるたびに、この余分な条件を含める必要があります。

助けてください! 私はこの問題は、あなたはケース非依存のnan記法をサポートしていますawkのを使用して数値ではない値で、数値の比較をしようとしているということであるバージョン20070501.

感謝

+1

はここでは再生できません。 'awk '$ 3 == 3''はあなたが望むものを与えます。 – Kent

+0

私は同僚の勧告にgawkをインストールすることでこの問題を解決しました。私はawkのバグの古いバージョンを使用していたと信じています。ありがとう – izzyrizzy

+0

いずれにしても、 'awk '$ 3 == 3' file'はあなたが望むコマンドです。行全体を表示するのがawkのデフォルトの動作なので、他のすべては余計です。 – hek2mgl

答えて

1

を実行している(そしておそらくよinfも)望ましくない結果が得られます。

通常、すべてのawk値は数値または文字列です。 nanはどちらも特別なので(一部のawksでは)awkかそれが使用する基本的なCプリミティブは何をするかを決める必要があります。

数値をnanと比較すると、最も賢明な選択は、数値がCANに等しくない(またはそれ以下でもない)nanであるため常に「失敗」することになりますが、明らかにawkプロバイダによってはあなたは発見しました。私は個人的にバグだと考えていましたが、数字の理論や、それがそうでないかというとnanの使用に関する標準の歴史については十分に分かりません。肩をすくめる。 --posixフラグのgawkなし

は、文字列としてnanを扱いますが、「特別な」数値として+nan-nanを扱います。 --posix gawkはnanの基本的なCプリミティブが実行中のシステム上にあると判断したものをそのまま扱います。これらの決定は、過去のプログラムを支援することであり、システムによって異なります。

あなたが入力NaNとき$3==3がfalseであるため--posixなしgawkは今あなたのために働いていると思いますけれども、それは実際にはないので、それだけで数値比較のために0に文字列を変換NaNています。

あなたの問題へのポータブルな解決策は、そうしないことです。 nan Sを含むことができ、あなたの入力データはその後、しかし、それらを処理するようにコードを記述する場合は、例えば、それらを扱うたい:

$ awk '$3!="NaN" && $3==3' file 
-101.358 80.775 3 

しかしgawk --posixは、既存のデータであなたがやりたいことになります。

$ gawk '$3==3' file 
-101.358 80.775 3 

$ gawk --posix '$3==3' file 
-101.358 80.775 3 

$ echo '1 2 NaN' | gawk '$3+0==0' 
1 2 NaN 

$ echo '1 2 NaN' | gawk --posix '$3+0==0' 
$ 

$ gawk '{print $2 - $3}' file 
77.775 
78.85 
80.976 
81.0566 

$ gawk --posix '{print $2 - $3}' file 
77.775 
78.85 
nan 
nan 
:WRTは nansに算術演算を実行し、結果もまた、あなたのデータを gawk --posixを必要とし、あなたのコメントで述べたように nan、も持ってできること

だから、gawk --posixはあなたが持っているデータから必要なすべての動作を提供しますが、数字に似た文字列を変換するための通常の切り捨て規則が適用されるので注意してください。

$ echo 'nanny' | gawk '{ print $1 + 0 }' 
0 

$ echo '+nannny' | gawk '{ print $1 + 0 }' 
nan 

$ echo 'nanny' | gawk --posix '{ print $1 + 0 }' 
nan 

また、POSIXモードでのgawkを使用すると、それのすべてのそれを取り除きそうgensub()のような便利な拡張機能だということに注意してください。代わりにゼロに変換の数値コンテキストで使用された場合、それはnanにマッピングされますnanを考慮より良いアプローチはnan+と接頭辞を付けることです。そうすればgawkはと認識できます--posixのハンディキャップを必要とせずに、あなたがnannyを書いたとき、あなたがnanを意味考えずにのS(上記参照):要約中のSO

$ echo 'nan' | gawk '{print ($1+0==0)}' 
1 

$ echo 'nan' | gawk --posix '{print ($1+0==0)}' 
0 

$ echo '+nan' | gawk '{print ($1+0==0)}' 
0 

$ echo '+nan' | gawk --posix '{print ($1+0==0)}' 
0 

$ echo '+nan' | gawk '{print ($1+0==0), gensub(/foo/,"bar",1)}' 
0 +nan 

$ echo '+nan' | gawk --posix '{print ($1+0==0), gensub(/foo/,"bar",1)}' 
gawk: cmd. line:1: warning: regexp constant for parameter #1 yields boolean value 
gawk: cmd. line:1: (FILENAME=- FNR=1) fatal: function `gensub' not defined 

$ cat file 
-101.358 80.775 3 
-100.187 80.850 2 
-98.019 80.976 +NaN 
-96.476 81.0566 +NaN 

$ gawk '{print $2 - $3}' file 
77.775 
78.85 
nan 
nan 

からgawk --posixがあなたの現在のデータで動作しますが、私はあなたのデータを変更することをお勧めしたいですNaNの代わりにを使用してください。--posixがなくてgawkで動作するので、非常に便利な拡張機能が多数あり、予期せずnanで始まる文字列を取得することはありません。 nanny)はnanに変換される。

+1

この詳細なお返事ありがとう – Thor

+1

あなたの詳細な返答ありがとうございました。 posixが本当に私の問題を解決するように見えます。あなたが私の元の質問の誤字を言ったように、私はそれを修正しました。これについての謝罪! – izzyrizzy

+0

ようこそ。はい、 '--posix'を追加するとあなたのデータを扱うことができますが、' NaN'ではなく '+ NaN'を使うようにデータを変更することをお勧めします。これは' --posix'なしでgawkで動作するので、gawks信じられないほど便利な拡張機能。 –

関連する問題