如何[不断]读取文件的最后一行?

如何[不断]读取文件的最后一行?

我让客户端从实时 MQTT 流中过滤出数据,并将数据写入文件中myfile.csv,以下是最后四行:

1426134425,m,NWRL,MSV,001,d,SVlts,139,1840343,26089,28529,15987
1426134444,m,NWRL,MSV,001,d,status,139,1859000,23911,-33.836465,151.051189
1426134834,m,gf,TMX6BP,075,d,SVlts,216,1243746,27209,27409,17106
1426134845,m,gf,TMX6BP,075,d,status,216,1254000,179583,-33.836465,151.051189

该文件不断更新。因此 csv 文件的最后一行会不断变化,但格式仍然相同。

问:如何myfile.csv使用 bash 读取文件的最后一行,其中第七个值是“status”而不是“SVlts”?阅读完后,如何将第 4 个、第 5 个和第 10 个值分配给 3 个不同的变量?我将推出这些值来更新 MySQL 表。

所以输出可能如下:

variable_1=TMX6BP
variable_2=075
variable_3=179583

如前所述,这三个变量将被推送/发送以更新 MySQL 表(需要这三个变量才能更新自身),直到下一行打印到myfile.csv.而且这种情况会一而再、再而三地发生。

答案1

这将从最后一行捕获您想要的信息file

$ IFS=, read -r a b c var_1 var_2 d e f h var_3 extra < <(tail -n1 file)
$ echo $var_1  $var_2  $var_3
TMX6BP 075 179583

怎么运行的

  • IFS=,

    这会暂时将字段分隔符设置为逗号。

  • read -r a b c var_1 var_2 d e f h var_3 extra

    这会将字段读入列出的变量。您可以选择任何您喜欢的名称。

    在上面,第一个字段分配给 shell 变量a,第二个字段分配给b,等等。之后剩下的所有内容var_3都分配给 shell 变量extra

  • < <(tail -n1 file)

    这提供了最后一行file作为命令的标准输入read。第一个<是用于重定向的 shell 符号。该构造<(...)称为进程替换。第一个和第二个之间的间距<基本的

答案2

简短回答:

   # tail -F: output appended data as the file grows
   #      Capital F to follow even if the file is reset to zero, recreated, etc.
   # awk -F, sets FS - Field Separator to a comma
   #   Inside awk: See if field 7 == "status" and print fields 4, 5 and 10
tail -F myfile.csv | awk -F, '$7 == "status" { print $4, $5, $10 }'

您没有写如何更新数据库,因此我会写一些可能帮助您入门的内容。

据我了解,您不会编辑 myfile.csv 文件,而是使用提到的 3 个变量作为更新脚本/作业的输入。错误检查等等,我就交给你了。

首先,创建更新 MySQL 数据库的脚本。我就在这里嘲笑一下吧。

#!/bin/bash
# update-MySQL-table.sh
    # redirecting stderr to stdout so awk will see it.
    # Not much use with "echo", but ...
echo $0 $1 $2 $3 2>&1

然后,您有另一个脚本来读取和解析您的 CSV 文件,并启动数据库更新脚本。

#!/bin/bash
# parse-my-CSV-file.sh
csvfile="myfile.csv"

tail -n0 -F $csvfile | \
    awk -F, '
        $7 == "status" {
            cmd=sprintf("./update-MySQL-table.sh %s %s %s",$4,$5,$10)
            cmd | getline output
            print output
    }'

然后启动解析脚本,您应该看到添加到 myfile.csv 中第七个字段中带有“status”的新行如何打印到 stdout。

答案3

我会做类似的事情:

tail -n1 -f file | 
  perl -MDBI -F, -lane 'BEGIN{$d = DBI->connect(...)}
    if ($F[6] eq "status") {
      $d->do("INSERT INTO foo VALUES (?,?,?)", @F[3,4,9]);
    }'

相关内容