我让客户端从实时 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]);
}'