私は深いシェルスクリプトの感情家ではありません。基本を知っていて、私の問題の提案に開いています。 1日24時間実行されるスクリプトを書く必要がありますが、正直なところ、どこから始めるべきかさえわかりません。次の状況でこのスクリプトをどのように組み立てるかをご存知ですか?
次のシナリオがあります。例1(今日起こったこと)と例2(予想結果)
実施例1
#価格_通知_製品ABC 価格:0.006813 変更:+1.6% カウント数:1 #価格_通知_製品ABC 価格:0.006969 変更:+2.3% カウント数:2 #価格_通知_製品ABC 価格:0.007060 変更:+1.3% カウント数:3 #価格_通知_製品ABC 価格:0.007300 変更:+3.4% カウント数:4 #価格_通知_製品ABC 価格:0.007453 変更:+2.1% カウント数:5
実施例2
#価格_通知_製品ABC 価格:0.006813 変更:+1.6% カウント数:1 #価格_通知_製品ABC 価格:0.006969 変更:+3.9% カウント数:2 #価格_通知_製品ABC 価格:0.007060 変更:+5.2% カウント数:3 #価格_通知_製品ABC 価格:0.007300 変更: +8.6% カウント数:4 #価格_通知_製品ABC 価格:0.007453 変化: +10.7% カウント数:5
必要:
1 - #Price_Notification_ProductABCエントリは固定アイテムではなく、検索で複数の製品(Price_Notification_ProductABC、#Price_Notification_ProductXYZ、#Price_Notification_Product123など)が返される可能性があるため、このアイテムを機能させるにはgrepを使用してアイテムを一致させる必要があると思います。このアイテムに関する通知を受け取りました
2 - 価格項目には事前定義された小数点以下の桁数が含まれていません。価格:0.006813価格:1.256価格:524.354などの形式であり、動的です。
3-アイテムの変更は説明するのが最も複雑です。例 1 に示すように、通知は常に少数の数値を含むパーセンテージを返します。
- 例2に示すように、合計を徐々に計算するフィルタが必要です。
- この増分合計は、常に前の通知の割合と現在の通知の割合を追加する必要があります。
- しかし、ここにはいくつかの条件があります。現在の通知の価格項目の値は、常に前の通知の値より大きくなければなりません。この条件が満たされない場合は、通知の合計/パーセントを含むループ/フィルタをリセットする必要があります。 、これにより、新しい通知期間が開始されます。
4 - プロジェクトの計算、計算も動的で、時間ごとに常にゼロにリセットされるため、このプロジェクトをどのように処理するのかわかりません。ただし、このプロジェクトの処理方法に関する提案を歓迎します。
私はこの方法でこの情報を得ており、これについて私ができることは何もないことに注意してください。私は受け取った情報に基づいて私に役立つスクリプトを書こうとしています。
また、2つの基準/条件を解決する必要があります。これら2つの条件のいずれかが存在する場合は、増加/増加パーセント計算をリセットして新しいループを開始する必要があります。
1-パーセントは増分式として計算する必要があります。ある通知と別の通知の間の0〜最大30分の範囲から31分から始まり、パーセンテージの増分計算をリセット/再開して新しい通知の計算を開始する必要があります。サイクル
2 - 価格アイテムから受信した最後の通知には、以前の通知より低い値を含めることはできません。たとえば、3つの新しい通知がありました(カウント:6、カウント:7、カウント:8)。
#価格_通知_製品ABC 価格:0.007023 変更:+1.8% カウント数:6 #価格_通知_製品ABC 価格:0.007184 変更:+2.3% カウント数:7 #価格_通知_製品ABC 価格:0.007328 変更:+3.3% 計算数量:8
この例では、Price: 0.007023
通知数が6の項目がPrice: 0.007453
通知数が5の前の項目よりも低いため、以前に行ったすべての計算を0に設定/再開する新しいループを開始する必要があります。
次のようにする必要があります。
#価格_通知_製品ABC 価格:0.007023 変更:+1.80% カウント数:6 #価格_通知_製品ABC 価格:0.007184 変更:+4.10% カウント数:7 #価格_通知_製品ABC 価格:0.007328 変更:+7.40% 計算数量:8
他の状況でこの問題を解決するための提案はありますか?
ありがとうございます!
ベストアンサー1
awk
これは見た目ほど難しくなく、またはで行うのは非常に簡単ですperl
。
パールの使用:
$ perl -lpe 'if (/^#Price_Notification_Product/) {
$prod = $_;
} elsif (/^change: ([^%]*)%/) {
$products{$prod} += $1;
$_ = "change: +$products{$prod}%";
}' input.txt
#Price_Notification_ProductABC
Price: 0.006813
change: +1.6%
Count Number: 1
#Price_Notification_ProductABC
Price: 0.006969
change: +3.9%
Count Number: 2
#Price_Notification_ProductABC
Price: 0.007060
change: +5.2%
Count Number: 3
#Price_Notification_ProductABC
Price: 0.007300
change: +8.6%
Count Number: 4
#Price_Notification_ProductABC
Price: 0.007453
change: +10.7%
Count Number: 5
- 行終端の自動処理を有効にするPerlオプション
-l
(入力から改行文字を削除し、それをprint
by文の出力に追加) - この
-p
オプションを使用すると、sedのように動作します(つまり、各入力行を読み取り、処理後に自動的に印刷します)。 -e
次の引数が実行されるスクリプトであることをPerlに通知します。
スクリプトは各入力行を読み取り、行が "#Price_Notification_Product"で始まる場合、現在の行を変数に保存します$prod
。
それ以外の行が "change:" で始まる場合は、次のようになります。
正規表現キャプチャを使用して変更された値を抽出し、その値を名前付きハッシュ(「連想配列」とも呼ばれる)に追加します
%products
。ハッシュのキーは製品名($prod
)です。#Price_Notification_Product...
各製品の行が一意で一貫性がある限り、入力で必要な数の製品名を処理できるようにハッシュを使用します。各製品名の累積合計は独立して追跡されます。$_
この製品の現在の累積合計を持つように現在の行(変数)を変更します。ただし、「change:」行に小数点の前後に固定の桁数を指定するには、を使用します
sprintf
。たとえば、$_ = "change...."
次のように行を変更できます。$_ = sprintf("change: %7.2f%%", $products{$prod}); s/(\d)/+$1/;
これにより、以下のように「change」行が出力されます。
change: +1.60% change: +3.90% change: +5.20% change: +8.60% change: +10.70%
すべての入力行は、変更の有無にかかわらず印刷されます。
入力はファイル(input.txt
私が使用したものと同じ)または標準入力(パイプなどtail -f
)から来ることができます。
ところで、製品の数がゼロにリセットされると、製品の累積合計をゼロにリセットしたいと思うかもしれません。この場合、最後の行を変更してください。
}' input.txt
これに関して:
} elsif (/^Count Number: 0$/) {
$products{$prod} = 0;
}' input.txt
スタンドアロンスクリプトと同じ:
#!/usr/bin/perl -lp
if (/^#Price_Notification_Product/) {
$prod = $_;
} elsif (/^change: ([^%]*)%/) {
$products{$prod} += $1;
$_ = "change: +$products{$prod}%";
}
#!
Perlインタプリタが別の場所にある場合は、正しいフルパスを参照するように行を調整する必要があります。
たとえば、次の名前で保存し、次のように実行可能./script.pl
にしますchmod +x script.pl
。
$ ./script.pl input.txt
または
$ perl -lp ./script.pl input.txt
awkバージョンのPerlバージョンを直接翻訳しましたが、各「change:」行の2番目のフィールドからアンパサンドをgsub()
削除する必要があります。+
%
$ awk '
/^#Price_Notification_Product/ {
prod = $0;
}
/^change: / {
gsub(/[+%]/,"",$2);
products[prod] += $2;
$2 = "+" products[prod] "%"
}
1' input.txt
awkスクリプトの最後の行はタイプ1
ミスではありません。これは、変更の有無にかかわらず、常に現在の行を印刷するようにawkに指示します(awkスクリプトはデフォルトで一連のPATTERN ACTIONルールです。PATTERNがtrueと評価されると、ACTIONが評価され 1
ます{print}
。