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

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

仕事:

stdoutは、ロード平均を上から小数点形式で出力します(例:0.23)。

詳細:

このスクリプトを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

進展

次のリソースを使用してください。平均負荷を得るにはtopを使用してください。

このコマンドを使用すると、出力はうまく表現されますが、出力は文字列なので計算できません。

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

ただし、printfを小数/浮動小数点に変更しようとするとエラーが発生します。

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

質問:

文字列値を10進数/浮動小数点/整数に変換するには?

ps -o user,rss出力:

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

答え1

~からgawk: カンマ区切り文字でフォーマットされた浮動小数点数の合計:

答えは--use-lc-numericgawkオプションを使用することです。

--use -lc-番号

これは、gawkが入力データを解析するときにロケールの10進文字を使用するように強制します。 POSIX 標準ではこの動作を要求し、gawk は --posix が適用されるときにそうしますが、デフォルトはピリオドが小数点ではなくロケールでもレガシー動作に従い、ピリオドを小数点として使用することです。性格。このオプションは、--posixオプションの完全な厳密さなしにデフォルトの動作をオーバーライドします。

あなたの場合、次のコマンドが機能します。

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

答え2

,小数点区切り記号を持つロケールを使用している可能性があります。次のいずれかの方法を試すことができます。

  1. C ロケールの使用top:

    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. awkまたは、次の POSIX 準拠の実装を使用します。本当のことはありません。 デフォルトでは、ロケールの規則に従って数値を解析して印刷する必要があります。

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

答え3

仕事:

sdout 上から小数点形式の負荷平均 (例: 0.23)

解決策:

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

メモ:

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

指摘したとおり@テデンuptimeこの例よりも良い出発点になることができます。top

最初の2行以降暗黙的に結果として何をしたいのかを説明してください。あなたが取りたい次のステップは新しい質問の主題でなければなりません。

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


質問2:

この部分は2番目の質問についてです。全く関係ない最初に。
OPにこの質問を別々に投稿するように促します。

文字列値を10進数/浮動小数点/整数に変換するには?

より良い書き方は、文字列に対して数値比較を実行することです。シェフ~の仕様確認

解決策:

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

例:

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

説明する:

stdoutが文字列として扱われることは完全に理解されています。それも非常に合理的に、数字比較するには、2つの数字が...数字でなければなりません。幸いなことに、便利なRuby文字列メソッドto_ito_fおよびを使用して変換を実行できます。to_rto_c

答え4

問題は、抽出されたフィールドが小数点区切り文字としてコンマを使用するのに対して、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

関連情報