当前月相

作者:Dave Taylor

女士们先生们,我们离开了火星。好吧,至少我完成了过去几篇文章中关于火星着陆器的内容。我希望你们有机会尝试一下,并发现将飞行器降落在任何行星上都不是那么容易!

在研究火星着陆器项目时,我偶然发现另一个与太空相关的有趣的脚本问题。如何确定给定日期的月相?当然,有公式,你可以通过数学计算得知月球的自转周期是精确的——嗯……实际上,并没有那么简单。

恒星周期与朔望周期

当然,你可以简单地说月球每 27.3 天绕地球运行一次,但那是相对于恒星的,即恒星轨道。月相(例如满月)之间的周期也称为朔望轨道,为 29.5 天。

因此,确定是否是满月的简单任务也涉及到一些数学计算。然后还有月球的照明水平相对于你在地球上的位置的问题。这很合理。智利蓬塔阿雷纳斯的满月与拉普兰的满月不同(尽管差别不大)。

长话短说,计算月球照明水平背后的数学运算并不像看起来那么简单。你可以取一个已知的满月日期和时间(例如,11 月 14 日上午 8:52 EST),并不断精确地加上 29.530 天或 42,523.20 分钟。

或者你可以抓取网站!

但说真的,你也可以让别人来完成这项工作,对吧?我的意思是,这个专栏毕竟只是关于一个 shell 脚本。那么,让我们看看 Google 是怎么做的!如果你查看 Google 以了解当前月相,它实际上引用了一个网站,如图 1 所示。

图 1. Google 报告当前月相。

在 Moon Giant 网站上深入挖掘一下,你可以看到有两种基本形式的 URL 可以生成所需的数据:指定的日期或仅是作为日期的“today”。通过访问此网站进行测试:http://www.moongiant.com/phase/today

指定日期,格式会稍微复杂一些:http://www.moongiant.com/phase/MM/DD/YYYY。

你可以使用它来找出美国新总统宣誓就职当天的月相:http://www.moongiant.com/phase/01/20/2017。(如果你猜是满月,那你就错了!)

月相,V1

这意味着你可以非常容易地编写一个简洁的脚本,通过简单地使用 curlGET 和这三个 URL 中的第一个来告诉你当前的月球照明水平


url="http://www.moongiant.com/phase/today"
pattern="Illumination:"
phase="$( curl -s "$url" | grep "$pattern" | tr ',' '\
' | grep "$pattern" | sed 's/[^0-9]//g')"
echo $phase

在我编写本文时(2016 年 10 月 3 日)快速运行脚本,输出结果相当令人困惑:“6”。六。这是什么意思?实际上,这只是照明水平,其他所有内容都从输出数据中删除了。

6% 的照明接近新月,但还差一点。新月实际上是在两天前的 10 月 1 日。

脚本中有趣的部分完全在 phase= 语句中。让我们解开它并仔细看看


curl -s "$url" |
grep "$pattern" |
tr ',' '\
' | grep "$pattern" |
sed 's/[^0-9]//g'

首先,如果你不熟悉 curl,请阅读手册页。它是一个非常棒、功能非常强大的实用程序,可以让你调试 Web 服务器、向 Web 页面发送查询(就像你是各种 Web 浏览器一样)、与 FTP 服务器交互,当然,还可以抓取 Web 页面的源代码以进行进一步分析。我正在为这项任务使用后一种技能。

一旦页面的源代码流入,管道中的下一步是提取包含照明水平的行。结果证明正是“Illumination:”,但不幸的是,它并没有单独出现在 HTML 源代码行中。事实上,这是一个非常复杂的输出行!这实际上是接下来两行的工作。

tr 的调用将每个逗号转换为硬回车符,有效地将一个非常长的行分解成许多较短的行。然后再次调用 grep 以提取现在进一步隔离的照明水平指示器。

最后,通过让 sed 删除所有不是数字的内容来删除多余的数据。最终结果?像 Illumination: 6% 这样的输入变成 “6”,并存储在变量 phase 中。明白了吗?

现在可以增强输出了


echo "The moon's current illumination level: $phase%"

稍微更容易理解的输出!

但它是什么月相?

然而,月相通常不是用其照明水平来描述的,并且还需要知道前一天的状态,因为这是你确定“盈”或“亏”的方式。

有些很容易:0% 是新月,25% 是四分之一月,50% 是半月,100% 是满月。或者真的是这样吗?实际上,月球有八个相位,而 50% 的照明被称为“四分之一月”,这令人困惑。

事实上,月相取决于它在新月 → 新月周期中的位置,因此满月之前的 50% 照明是“上弦月”相位,而满月之后的 50% 照明是“下弦月”相位——非常复杂。

再次,让我们简化一下。所以现在跳过盈亏,而是使用以下内容

  • 0–5% = 新月。

  • 6–45% = 眉月。

  • 46–55% = 上弦月/下弦月。

  • 56–95% = 凸月。

  • 96–100% = 满月。

现在让我们编写代码。最简单的方法是使用一系列 if-then-else 语句


if [ $phase -lt 5 ] ; then
 phasename="new"
elif [ $phase -lt 45 ] ; then
 phasename="crescent"
elif [ $phase -lt 55 ] ; then
 phasename="quarter"
elif [ $phase -lt 95 ] ; then
 phasename="gibbous"
else
 phasename="full"
fi

具有美观的结果


$ potm.sh
The moon is currently crescent with 11% illuminated.

让我们在本文中就此打住。在我的下一篇文章中,我将添加分析它是盈月还是亏月的能力(例如,将昨天的照明水平与今天的进行比较,以查看月球是变亮还是变暗)。

Dave Taylor 在 UNIX 和 Linux 系统上编写 shell 脚本已经很长时间了。他是 Learning Unix for Mac OS XWicked Cool Shell Scripts 的作者。你可以在 Twitter 上找到他 @DaveTaylor,你也可以通过他的技术问答网站联系他:Ask Dave Taylor

加载 Disqus 评论