【问题标题】:bash script with string extract sometimes extracts wrong带有字符串提取的 bash 脚本有时会提取错误
【发布时间】:2018-02-21 03:01:29
【问题描述】:

作为序言:我上一次写“代码”是在大约 20 年前。这是学校里的一些 QBasic 脚本。 我的 ISP 严重限制了我的 Netflix 流量,而且到处都是混蛋,我没有得到全部带宽(我知道这是“尽力而为”,但仍然如此)。所以我买了一个 RPi3,去谷歌,疯狂地抄袭别人的代码。

现在我有一个 Python 脚本(应该是众所周知的)speedtest.py,我有一个 bash 脚本,它提取相关内容并将其写入 MySQL 数据库。

# temp file holding output to snip it
user=$USER
if test -z $user; then
  user=$USERNAME
fi
log=/tmp/$user/speedtest-mysql.log

# Local functions
str_extract() {
 pattern=$1
 # Extract
 res=`grep "$pattern" $log | sed "s/$pattern//g"`
 # Drop trailing ...
 res=`echo $res | sed 's/[.][.][.]//g'`
 # Trim
 res=`echo $res | sed 's/^ *//g' | sed 's/ *$//g'`
 echo $res
}

mkdir -p `dirname $log`

# run speedtest
/usr/local/bin/speedtest --share > $log

# parse the output
from=`str_extract "Testing from "`
from_ip=`echo $from | sed 's/.*(//g' | sed 's/).*//g'`
from=`echo $from | sed 's/ (.*//g'`

server=`str_extract "Hosted by "`
server_ping=`echo $server | sed 's/.*: //g'`
server=`echo $server | sed 's/: .*//g'`
server_dist=`echo $server | sed 's/.*\\[//g' | sed 's/\\].*//g'`
server=`echo $server | sed 's/ \\[.*//g'`

download=`str_extract "Download: "`
upload=`str_extract "Upload: "`
share_url=`str_extract "Share results: "`

#create timestamp for database
timestamp=`date +"%Y-%m-%d %H:%M:%S"`

# Send to MySQL

value1=`echo $server_ping | cut -d" " -f1`
value2=`echo $download | cut -d" " -f1`
value3=`echo $upload | cut -d" " -f1` 

sql="INSERT INTO $db_table (timestamp,ping,download,upload,server,share_url) VALUES ('$timestamp','$server_ping','$download','$upload','$server','$share_url');"

echo "$sql" | mysql -u$db_user -p$db_passwd -h$db_host $db_name

现在的问题是:有时我从速度测试中获得 95.53 MBit/s 下载和 9.93 MBit/s 上传的输出,但我的数据库中的上传值为 0.90。 写入日志文件的speedtest.py相关输出:

Retrieving speedtest.net configuration...
Testing from UPC Austria (80.110.109.207)...
Retrieving speedtest.net server list...
Selecting best server based on ping...
Hosted by Timewarp IT Consulting GmbH (Vienna) [2.79 km]: 32.403 ms
Testing download speed................................................................................
Download: 17.46 Mbit/s
Testing upload speed................................................................................................
Upload: 2.28 Mbit/s
Share results: http://www.speedtest.net/result/7075502570.png

如前所述:我上一次编码之旅是在 90 年代,我的 google-fu 无法找到我解决这个问题的方法。有人可以帮忙吗?

【问题讨论】:

  • 您可以删除 pythonraspberry-pi 标签,或者添加脚本的相关部分。很可能是一些转换问题。
  • 在上面添加了相关输出。
  • 这里有很多遗漏的引号。考虑通过shellcheck.net 运行它并修复它发现的内容。用尽可能短的代码构建一个 minimal reproducible example 来演示一个问题也会很有帮助——例如,如果你不运行 /usr/local/bin/speedtest 而只是编写了一个硬编码的字符串,那么没有安装 speedtest 的人可以运行脚本自己查看问题,从而能够测试他们(或其他人)提出的修复。
  • /usr/local/bin/speedtest 实际上是来自github.com/sivel/speedtest-cli/blob/master/speedtest.py 的python 脚本我将编辑我上面的代码以更好地阅读并使用引号。

标签: bash


【解决方案1】:

正如 Charles 在 cmets 中所建议的,这个脚本有很多可以改进的地方。虽然shellcheck.net 可以帮助您识别脚本的问题,但它对策略 的帮助不大。

在我看来,您可以通过以下方式消除许多麻烦:

#!/usr/bin/env bash

IFS=,

a=( $(/usr/local/bin/speedtest.py --csv) )

fmt="INSERT INTO %s (timestamp,ping,download,upload,server)
  VALUES ('%s',%.2f,%.2f,%.2f,'%s')"

printf -v sql "$fmt" "${a[4]}" "${a[6]}" "${a[7]}" "${a[8]}" "${a[3]}"

mysql -u"$db_user" -p"$db_passwd" -h"$db_host" -e "$sql" "$db_name"

此解决方案假定speedtest.py 永远不会产生在带引号的字符串中嵌入逗号的输出。不知道“赞助商”字段是否包含逗号,您可以根据需要添加错误检查,甚至可以仅通过计算字段。

CSV 输出被加载到数组 $a[] 的字段中,printf 在填充 $sql 变量时访问该数组。

您当然会调整格式以满足您的要求。为了便于阅读,上面的脚本使用了比它严格需要的更多的变量。

请注意,--csv--share 选项似乎是互斥的。

【讨论】:

    猜你喜欢
    • 2022-10-19
    • 2017-02-05
    • 2014-11-05
    • 2012-07-06
    • 2023-03-20
    • 2015-04-26
    • 2021-01-21
    • 1970-01-01
    • 2020-09-03
    相关资源
    最近更新 更多