帮助创建 shell 脚本

帮助创建 shell 脚本

我不是一个深入的 shell 脚本行家,我知道基础知识,并且愿意接受针对我的问题的建议,我需要编写一个每天 24 小时运行的脚本,但老实说,我什至不知道从哪里开始,知道如何根据下面的情况组装这个脚本吗?

我有以下场景,示例 1(这就是今天的情况)和示例 2(预期结果)

实施例1

#Price_Notification_ProductABC
价格:0.006813
变化:+1.6%
计数数量:1

#Price_Notification_ProductABC
价格:0.006969
变化:+2.3%
计数数量:2

#Price_Notification_ProductABC
价格:0.007060
变化:+1.3%
计数数量:3

#Price_Notification_ProductABC
价格:0.007300
变化:+3.4%
计数数量:4

#Price_Notification_ProductABC
价格:0.007453
变化:+2.1%
计数数量:5

实施例2

#Price_Notification_ProductABC
价格:0.006813
变化:+1.6%
计数数量:1

#Price_Notification_ProductABC
价格:0.006969
变化:+3.9%
计数数量:2

#Price_Notification_ProductABC
价格:0.007060
变化:+5.2%
计数数量:3

#Price_Notification_ProductABC
价格:0.007300
变化:+8.6%
计数数量:4

#Price_Notification_ProductABC
价格:0.007453
变化:+10.7%
计数数量:5

要求:

1-项目 #Price_Notification_ProductABC 不是固定项目,搜索可以返回多个产品(Price_Notification_ProductABC、#Price_Notification_ProductXYZ、#Price_Notification_Product123 等),因此,为了使其正常工作,我认为有必要使用 grep 进行匹配收到的关于该项目的第一个通知

2- 价格项没有预定义的小数位,它可以采用格式 Price: 0.006813 Price: 1.256 Price: 524.354 等,它是动态的

3- 更改项目是最复杂的解释,通知返回包含始终为小数的数字的百分比,如示例 1 所示,

  • 我想要一个过滤器,它可以增量地进行计算总和,如示例 2 所示
  • 此增量总和必须始终添加上一个通知的百分比 + 当前通知的百分比
  • 但为此需要有一些条件: 当前通知的 Price 项的值必须始终大于前一个通知的值,如果不满足此条件,则包含通知总和/百分比的循环/过滤器必须被重置,从而开始新的后续通知周期

4-计数项目,我真的不知道如何处理这个项目,因为计数也是动态的,并且总是每小时重置为 0,但我愿意接受有关如何处理这个项目的建议


请注意,我通过这种方式获取此信息,对此我无能为力,我正在尝试构建一个根据收到的信息为我服务的脚本。

我还需要解决两个标准/条件,当这两个条件之一存在时,必须重置增量/增加百分比计算,开始新的循环

1- 百分比需要增量计算,在一个通知与另一个通知之间的 0 到最多 30 分钟的窗口内,从第 31 分钟开始,需要重置/重新启动百分比的增量计算,开始新的通知计算周期

2- 从价格项收到的最后一个通知不能包含低于前一个通知的值,例如,我又收到了三个新通知(计数编号:6、计数编号:7 和计数编号:8)

#Price_Notification_ProductABC
价格:0.007023
变化:+1.8%
计数数量:6

#Price_Notification_ProductABC
价格:0.007184
变化:+2.3%
计数数量:7

#Price_Notification_ProductABC
价格:0.007328
变化:+3.3%
计数数量:8

在此示例中,由于Price: 0.007023通知计数编号:6 的项目的值低于Price: 0.007453前一个通知计数编号:5 的项目的值,因此我需要启动一个新循环,将之前完成的所有计算清零/重新启动。

它应该看起来像这样:

#Price_Notification_ProductABC
价格:0.007023
变化:+1.80%
计数数量:6

#Price_Notification_ProductABC
价格:0.007184
变化:+4.10%
计数数量:7

#Price_Notification_ProductABC
价格:0.007328
变化:+7.40%
计数数量:8

有什么建议来解决这个其他情况吗?

谢谢!

答案1

awk这并不像看起来那么困难,在或中相当容易做到perl

使用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选项打开自动处理行结束符(例如,从输入中去除换行符,将它们添加到 byprint语句的输出中)
  • -p选项使其像 sed 一样工作(即读取每个输入行并在任何处理后自动打印它)
  • -e告诉 perl 下一个 arg 是要执行的脚本。

该脚本读取每个输入行,如果该行以“#Price_Notification_Product”开头,则将当前行存储在变量中$prod

否则,如果该行以“change:”开头,则:

  • 使用正则表达式捕获提取更改的值,并将该值添加到名为 的散列(也称为“关联数组”)中%products。哈希值的关键是产品名称 ( $prod)。

    它使用散列,以便可以处理输入中任意数量的产品名称 - 只要#Price_Notification_Product...每个产品的行是唯一且一致的。每个产品名称的累计总数将被独立跟踪。

  • 更改当前行(变量$_),使其具有该产品的当前累计总计。

    顺便说一句,如果您希望“change:”行在小数点之前和/或之后具有固定位数,您可以使用sprintf.例如,将该$_ = "change...."行更改为:

               $_ = sprintf("change: %7.2f%%", $products{$prod});
               s/(\d)/+$1/;
    

    这将输出“更改”行,如下所示:

    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:”行的第二个字段中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评估为 true,默认操作为{print})

相关内容