bash 脚本中的间歇性语法错误涉及 echo、python 脚本、grep、sed、bc 和日期

Intermittent syntax error in a bash script involving echo, a python script, grep, sed, bc, and date

我写了一个 python 脚本来从 Raspberry Pi Astro“Sense Hat”传感器进行磁场测量。它被称为“mag-AstroPi.py”:

#!/usr/bin/python
from sense_hat import SenseHat
sense = SenseHat()
raw = sense.get_compass_raw()
#print(x: {x}, y: {y}, z: {z}.format(**raw))
#alternatives
print(sense.compass_raw)

这是感知帽厂商element14提供的脚本

该脚本以微特斯拉的形式输出三个轴(X、Y 和 Z)的磁场数据,以及一堆额外的字符:

pi@raspberrypi ~ $ python mag-AstroPi.py

{'y': 13.895279884338379, 'x': -1.1642401218414307, 'z': -0.4132799804210663}

我需要删除多余的字符,将这些值乘以 1,000 以将它们转换为纳米特斯拉(我的特定应用程序的标准 SI 单位),然后将乘积值与日期和时间一起记录到一个文件中。这需要每两秒发生一次。

我想要三个单独的日志文件 - 一个用于 X 轴,一个用于 Y 轴,一个用于 Z 轴。但是,目前,我只处理 Y 轴数据。一旦我让 Y 轴数据记录工作,我就可以复制和改变其他两个轴。

所以我写了一个 bash 脚本,AstroPiMagLogger.sh,它 运行 通过 cron 作业启动:

#!/bin/bash
while true
do
        echo $(python mag-AstroPi.py -n | grep "y" | cut -d " " -f2 | cut -c 1-18 | sed 's/$/*1000/' | bc; date +"%Y,%m,%d,%T,%Z") >> rawysecnT.txt
        sleep 2
done

应该只提取 Y 轴值,将其乘以 1,000,然后将其与当前日期、时间和时区一起保存到一个新的文本文件中, rawysecnT.txt.

有效,有点...这是rawysecnT.txt的内容:

13703.761100769043000 2015,09,14,08:56:41,UTC

13703.761100769043000 2015,09,14,08:56:44,UTC

13613.041877746582000 2015,09,14,08:56:46,UTC

13794.480323791504000 2015,09,14,08:56:49,UTC

13804.560661315918000 2015,09,14,08:56:52,UTC

13875.120162963867000 2015,09,14,08:56:55,UTC

13633.201599121094000 2015,09,14,08:56:58,UTC

2015,09,14,08:57:00,UTC

2015,09,14,08:57:03,UTC

13744.080543518066000 2015,09,14,08:57:06,UTC

14016.241073608398000 2015,09,14,08:57:09,UTC

如您所见,它在大多数时间都有效。但是时不时地,它不会将磁场测量记录到文件中;它只记录日期和时间。

今天早些时候,我的日志记录工作正常,但那是在我添加将磁数据乘以 1000 的代码之前(即今天早些时候,脚本只记录微特斯拉中的原始磁数据,以及date/time)。我有几个小时的数据,没有任何错误,所以很明显我在添加磁测量乘法代码时填充了一些东西。

我决定运行下面直接在命令行中(而不是通过脚本),以便调试。

echo $(python mag-AstroPi.py -n |grep "y" | cut -d " " -f2 | cut -c 1-18 | sed 's/$/*1000/' | bc; date +"%Y,%m,%d,%T,%Z")

不出所料,这工作了大约十几次,终端打印了以下输出,这正是我想要的:

14167.440414428711000 2015,09,14,09:07:30,UTC

然后,最后一次,它返回了以下错误:

(standard_in) 1: syntax error

2015,09,14,09:07:59,UTC

鉴于错误是间歇性的,而且我对编程还很陌生(我只接触了大约一个月),所以我不知道可能是什么问题。

我很感激任何人可能对为什么这在大多数时间但不是所有时间都有效的想法。


评论中要求的两个示例输出如下:

pi@raspberrypi ~ $ python mag-AstroPi.py -n | grep "y" | cut -d " " -f2 | cut -c 1-18 | sed 's/$/*1000/' | bc; date +"%Y,%m,%d,%T,%Z" 
14076.720237731934000 2015,09,14,09:53:33,UTC 

pi@raspberrypi ~ $ python mag-AstroPi.py -n 
{'y': 13.935601234436035, 'x': -1.506960153579712, 'z': 0.24192002415657043}

看起来您正在尝试做的事情可以(并且几乎肯定应该)在 Python 脚本本身内完成。 get_compass_raw() 返回给你一个字典,所以你可以直接提取 y 值(并乘以 1000):

raw = sense.get_compass_raw()
y_component_nT = raw['y'] * 1000

要添加您的时间戳,我会使用内置的 datetime 模块:

from datetime import datetime
now = datetime.now()

然后您可以根据需要格式化时间,使用 now.strftime(format),其中 format 是一个格式字符串,如 the docs 所示。

我将在 python 中将写入文件和暂停执行的挑战留给您 - 这些问题已经包含在本网站和其他地方的许多好的答案中。

显然,如果没有 Sense Hat 传感器,我无法正确测试此代码,但您应该会发现它很有帮助。它会无限循环,所以你需要给它发送一个 CtrlC 来杀死它。

#!/usr/bin/env python

import time
from sense_hat import SenseHat

sense = SenseHat()

#Un-comment the following line to ensure the compass is on and the gyro & accelerometer are off
#sense.set_imu_config(True, False, False)

while True:
    raw_field = sense.get_compass_raw()
    now = time.strftime("%Y,%m,%d,%X,%Z")
    print(raw_field['y'] * 1000, now)
    time.sleep(2)

如果您使用 Python 2,则需要删除 print 行中的括号,或在其他 import 行之前添加 from __future__ import print_function

调整此代码以直接写入命名文件而不是通过管道输出并不难。但我会把它留作 Reader 的练习。 :) 而且修改它也很容易,写入 x、y 和 z 的 3 个文件。


怀疑 有时 SenseHat 根本没有 return 预期的磁场数据,但很难从你发布的信息中判断它是什么 does return 当它这样做的时候。它可能 return 是一个包含空数据值的字典,或者它可能 return 一个完全空的字典。

因此,如果您仍然得到错误的输出,请告诉我它是什么样子以及任何相关的错误消息,我应该能够告诉您如何修复它。

我同意这在 Python 脚本本身中完成得更好,如果您不熟悉 Python,这是学习它的一些小部分的好机会。至于你的管道,我认为关键问题在cut -c 1-18 | sed 's/$/*1000/' | bc。浮点数不能保证是特定的宽度甚至格式,因为您只是在没有请求任何格式的情况下打印字典,所以有时这将包括逗号(或最后一个组件的最后一个大括号),或者采用科学计数法,例如2.34e-07。 bc 不理解那些形式。此外,由于脚本只打印包含所有值的一行,因此 grep 什么都不做。

如果我要使用这样的管道来提取值,我可能会使用 sed -e "s/.*'y': \([-Ee.0-9]*\).*//" -e "s/[Ee]\(.*\)/*10^/" 之类的东西而不是剪切(后者将 e 形式转换为 bc 兼容表达式)。最重要的是,bc 有一些关于精度的特定规则,这意味着指数处理需要您设置 scale 否则一切都变为零。