【问题标题】:Print statement prints twice in outer block in perl打印语句在 perl 的外部块中打印两次
【发布时间】:2018-05-23 09:47:53
【问题描述】:

以下是改编自this link 的代码,用于获取天气并在 i3blocks 上显示。

#!/bin/bash 

METRIC=1 #Should be 0 or 1; 0 for F, 1 for C

if [ -z $1 ]; then
    echo
    echo "USAGE: weather.sh <locationcode>"
    echo
    exit 0;
fi

curl -s http://rss.accuweather.com/rss/liveweather_rss.asp\?metric\=${METRIC}\&locCode\=$1 | perl -ne 'use utf8;

if ( /Currently/ ) {

    chomp;
    /\<title\>Currently: (.*)?\<\/title\>/;

    my @values  = split(":", $1); 
    my $deg     = "°C";
    my @values2 = split("C", $values[1]);

    if ( $values[0] eq "Sunny" || $values[0] eq "Mostly Sunny" || $values[0] eq "Partly Sunny" || $values[0] eq "Intermittent Clouds" || $values[0] eq "Hazy Sunshine" || $values[0] eq "Hazy Sunshine" || $values[0] eq "Hot") {
        my $sun = "";
        binmode(STDOUT, ":utf8");
        print "$sun";
    }

    if ( $values[0] eq "Mostly Cloudy" || $values[0] eq "Cloudy" || $values[0] eq "Dreary (Overcast)" || $values[0] eq "Fog" ) {
        my $cloud = "";
        binmode(STDOUT, ":utf8");
        print "$cloud";
    }

    if ( $values[0] eq "Showers" || $values[0] eq "Mostly Cloudy w/ Showers" || $values[0] eq "Partly Sunny w/ Showers" || $values[0] eq "T-Storms"|| $values[0] eq "Mostly Cloudy w/ T-Storms"|| $values[0] eq "Partly Sunny w/ T-Storms"|| $values[0] eq "Rain" ) {
        my $rain = "";
        binmode(STDOUT, ":utf8");
        print "$rain";
    }

    if ( $values[0] eq "Windy" ) {
        my $wind = "";
        binmode(STDOUT, ":utf8");
        print "$wind";
    }

    if ( $values[0] eq "Flurries" || $values[0] eq "Mostly Cloudy w/ Flurries" || $values[0] eq "Partly Sunny w/ Flurries"|| $values[0] eq "Snow"|| $values[0] eq "Mostly Cloudy w/ Snow"|| $values[0] eq "Ice"|| $values[0] eq "Sleet"|| $values[0] eq "Freezing Rain"|| $values[0] eq "Rain and Snow"|| $values[0] eq "Cold" ) {
        my $snow = "";
        binmode(STDOUT, ":utf8");
        print "$snow";
    }

    if ( $values[0] eq "Clear" || $values[0] eq "Mostly Clear" || $values[0] eq "Partly Cloudy"|| $values[0] eq "Intermittent Clouds"|| $values[0] eq "Hazy Moonlight"|| $values[0] eq "Mostly Cloudy"|| $values[0] eq "Partly Cloudy w/ Showers"|| $values[0] eq "Mostly Cloudy w/ Showers"|| $values[0] eq "Partly Cloudy w/ T-Storms"|| $values[0] eq "Mostly Cloudy w/ Flurries" || $values[0] eq "Mostly Cloudy w/ Snow" ) {
        my $night = "";
        binmode(STDOUT, ":utf8");
        print "$night";
    }

    binmode(STDOUT, ":utf8");
    print  "$values2[0]$deg"; 
}'

(可能看起来像框的文本来自 fontawesome 字体)。我只添加了以下几行

my $deg = "°C";
my @values2 = split("C",$values[1]);

并修改了最后一个 print 语句,它最初是 print "$values[1]"。旧的print 语句显示的温度没有像35C 这样的度数符号。我的意图只是在35°C 之间添加度数,但输出是

35°C°C

为什么子字符串打印两次?即使我将它包含在单独的 print 语句中或直接包含子字符串 (print $values2[0]°C),也会发生这种情况。

奇怪的是,包括print "$sun$values2[0]$deg"; 等内部块中的值和单位似乎可以正常工作而不会重复。

【问题讨论】:

  • 您的代码在使用use strict 运行时出现语法错误。对于雪,存在复制/粘贴错误,因为变量名为$rain。当我只用一行 ($_ = '&lt;title&gt;Currently: Sunny&lt;/title&gt;';) 运行程序时,我无法重现您的问题。我尝试为每个 if 块设置一个值。它必须是你的输入。 RSS 提要可能包含两次触发词。请edit 并包含输入。
  • use utf8 pragma 旁边添加 use strictuse warnings pragma。你会看到出现两个问题。一是变量名错误,二是与数组有关。我没有调查他们,因为我没有真正的意见。
  • 告诉我们locCode,以便我们打开网址。
  • @simbabque。 locCode"ASI|IN|IN031|MADRAS"
  • @simbabque 关于$rain,代码中似乎存在错误。它的第二次出现应该是$snow(在编辑中修复了错误)。

标签: perl printing weather-api i3


【解决方案1】:

该脚本通过在 RSS 中查找 &lt;title&gt; 标记来工作。如果您手动执行此操作,您会看到有几个。'

curl -s 'http://rss.accuweather.com/rss/liveweather_rss.asp?metric=1&locCode=ASI|IN|IN031|MADRAS' | grep title
<title>Madras, IN - AccuWeather.com Forecast</title>
            <title>Madras, IN - AccuWeather.com Forecast</title>
            <title>Currently: Partly Sunny: 35C</title> 
                <title>5/23/2018 Forecast</title>
                <title>5/24/2018 Forecast</title>
<title>The AccuWeather.com RSS Center</title>

如果你添加

use strict;
use warnings;

您会收到大量关于未定义变量的警告。那是因为它没有找到与该模式匹配的 title,但它仍然会打印。

  if (/Currently/) {
    chomp;
    /\<title\>Currently: (.*)?\<\/title\>/;

    # ....
    print "$values2[0]$deg";
  }

这也是您获得额外输出的原因。

如果没有匹配,则需要跳过该行。

/\<title\>Currently: (.*)?\<\/title\>/ or next;

【讨论】:

  • 非常感谢!为什么一个变量被打印两次而另一个保持不变仍然很奇怪。你是对的。我只能通过附加的编译指示看到它。
  • 其实最外层if的测试应该是/&lt;title&gt;Currently: (.*)?&lt;\/title&gt;/——检查两次是没有意义的。
  • @Borodin 是的,你是对的。最重要的是,模式中有太多的转义。另一个迹象表明该代码的作者并不真正知道他们在做什么。 :-/
  • 可选的(.*)?也很可疑。
  • 换个说法,为什么不看看窗外的天气呢?我一直不明白为什么我需要一个只告诉我现在所在地方的天气的工具。看了预告,是的。但是对于现在的快照,我会转过头去外面抢劫。 :D
最近更新 更多