web-dev-qa-db-ja.com

awk printf文字列を10進数に変換する

タスク:

(例えば0.23)のような10進数形式で上からロード平均をstdout

詳細:

このスクリプトを解析してChefのインスペックに変換し、その結果が何かよりも大きいか小さいかを確認する必要があります。次に例を示します。

describe command("top -b -n  1  | awk  '/load average/ { sub(/,/,\".\",$10); printf \"%f\n\",$10}'") do
  its("stdout") { should eq 0.00 }    
end

この例は ""を返します

しかし、今考えると、/proc/loadavgのファイルと比較できます

進捗状況

このリソースを使用: 負荷平均を上部で取得

このコマンドを使用すると、出力を適切に表現できますが、これは文字列であり、数学的な操作を実行できません。

martin@martinv-pc:~$ top -b -n  1  | awk '/load average/ { printf "%s\n", $10}'
0,63,

しかし、printfをdecimal/floatに変更しようとすると、エラーが発生します。

martin@martinv-pc:~$ top -b -n  1  | awk '/load average/ { printf "%f\n", $10}'
0.000000
martin@martinv-pc:~$ top -b -n  1  | awk '/load average/ { printf "%d\n", $10}'
0

エコーできません、カットしてみました、悪い考え-機能していません:

martin@martinv-pc:~$ top -b -n  1  | awk '/load average/ { printf "%s\n", $10}'|cut -c1-4
0,15
martin@martinv-pc:~$ top -b -n  1  | awk '/load average/ { printf "%s\n", $10}'|$((cut -c1-4))
-4: command not found

別の試み:

martin@martinv-pc:~$ top -b -n  1  | awk '/load average/ BEGIN { printf "%.f\n", $10};'
awk: line 1: syntax error at or near BEGIN

質問:

文字列値をdecimal/float/integerに変換するにはどうすればよいですか?

ps -o user,rss出力:

[vagrant@localhost ~]$ ps -o user,rss
USER       RSS
vagrant    736
vagrant   1080
3
murloc

タスク:

次のような10進形式で負荷平均を上からsdoutします(例:0.23)

ソリューション:

top -b -n  1  | Perl -lane 'print "$1.$2" if /load average: (\d+)[,.](\d+)/'

注:

これにより、1mの負荷平均が取得されます。これはあなたが望んでいることのように見えますが、明確に述べる必要があります。必要に応じて、コードを簡単に変更して、5分または15分、あるいは3つすべての平均負荷を取得できます。

@ terdon で指摘されているように、この場合、uptimetopよりも優れた出発点になる可能性があります。

最初の2行の後に、obscurely結果で何をしたいかを記述します。実行したい後続のステップは、新しい質問の対象になるはずです。

Perlでは、数値は文字列に自動キャストされ、その逆も同様です。数値を表す文字列に対して数値演算を実行できます。例えばprint "$1.$2"+11.11


質問2:

この部分は、2番目の質問に関するもので、最初の質問とはまったく関係がないです。
OPにこの質問を個別に投稿することをお勧めします

文字列値をdecimal/float/integerに変換するにはどうすればよいですか?

より良い記述: Chef 's InSpec を使用した文字列の数値比較の実行。

ソリューション:

文字列をto_iまたはto_fを使用して数値形式に変換します。

例:

describe command("echo 1.00") do
    its("stdout.to_f") { should be < 1.03 }
end

説明:

非常に合理的に、stdoutは文字列として扱われます。また、非常に合理的に、numeric比較では、2つの数値を...数値にする必要があります。幸い、変換は便利なRuby文字列メソッド:to_ito_fto_rおよびto_cを使用して行うことができます。

1
simlev

From gawk:カンマ区切りでフォーマットされたフロートの合計

答えは--use-lc-numeric gawkオプション。

--use-lc-numeric

これにより、gawkは入力データを解析するときにロケールの小数点文字を使用するようになります。 POSIX標準ではこの動作が必要ですが、-posixが有効な場合、gawkでも必要ですが、デフォルトでは従来の動作に従い、ピリオドが小数点文字ではないロケールでも、ピリオドを小数点として使用します。このオプションは、--posixオプションの完全な厳格な厳密性なしで、デフォルトの動作を上書きします。

あなたの場合、このコマンドはうまくいくはずです:

top -b -n 1 | awk --use-lc-numeric '/load average/ { printf "%f\n", $10}'

2
Leo

おそらく、小数点記号として,を持つロケールを使用しています。次のいずれかの方法を試すことができます。

  1. topにはCロケールを使用します。

    LC_ALL=C top -b -n  1  | awk  '/load average/ { printf "%f\n",$10}'
    

    これは、ピリオドとコンマの問題に対処するだけでなく、load averageのようなテキストがユーザーの言語に翻訳される問題も回避します。

  2. コンマをドットに置き換えます。

    top -b -n  1  | awk  '/load average/ { sub(/,/,".",$10); printf "%f\n",$10}'
    
  3. GNU awkの場合、--use-lc-numericフラグを使用 @ Leoが推奨 またはPOSIXLY_CORRECT=1 awkを使用。

  4. または One True awk のようなPOSIX準拠のawk実装を使用して、デフォルトでロケールルールに従って数値を解析および出力する必要があります。

負荷平均を取得するためのより移植性の高いコマンドはuptimeです。

2
terdon

あなたの問題は、抽出されたフィールドが小数点記号としてコンマを使用していて、awkが浮動小数点がドットを使用することを期待していることです。

これはあなたの問題を再現します:

$ LC_ALL=de_DE top -bn 1 | awk 'NR==1'
top - 08:37:07 up 1 day, 10:22,  5 users,  load average: 0,17, 0,24, 0,26

ご覧のとおり、数値は小数点記号としてカンマを使用しています。次のようなものが必要です。

$ LC_ALL=en_US top -bn 1 | awk 'NR==1'
top - 08:38:28 up 1 day, 10:23,  5 users,  load average: 0.56, 0.34, 0.30

しかし、それはインストールされているロケールに依存します(locale -a)をシステムにインストールします。 Cロケールは常に利用可能です。

$ LC_ALL=C top -bn 1 | awk 'NR==1'
top - 08:40:35 up 1 day, 10:25,  5 users,  load average: 0.50, 0.39, 0.31

しかし、topを使用して最初の行のみを抽出するのはやり過ぎです。稼働時間の改善:

$ LC_ALL=C uptime
08:42:08 up 1 day, 10:27,  5 users,  load average: 0.35, 0.37, 0.31

しかし、さらに良いのは、/proc/loadavgファイル

$ cat /proc/loadavg 
0.29 0.34 0.30 1/468 15084

ちなみに、これはロケールの影響を受けません。最初の数値は1分の負荷平均です。それを選択して、任意の形式で印刷します。

$ awk '{printf( "%s\n %f\n %d\n", $1, $1, $1 )}' /proc/loadavg
0.35
0.350000
0

1、5、15分の負荷平均の使用:

$ awk '{printf( "%7.3f %7.3f %5.2f\n", $1, $2, $3 )}' /proc/loadavg
 0.150   0.340  0.33
1
Isaac