How to get just current average temperature from wttr.in curl result with bash? How to get just current average temperature from wttr.in curl result with bash? curl curl

How to get just current average temperature from wttr.in curl result with bash?


wttr.in now supports one-line output with custom format, so this

curl wttr.in/Amsterdam?format=%t

returns just the temperature, and as far as I can tell, it returns a single value instead of a range.


Previous version of answer

Based on the assumption that we have to modify the response ourselves

The main difficulty with this is that the service returns terminal escape codes, which make it messy to process. This is what you really get:

$ curl -s wttr.in/Amsterdam | grep -m 1 '°.' | cat -A ^[[38;5;226m _ /""^[[38;5;250m.-.    ^[[0m ^[[38;5;048m5^[[0m M-bM-^@M-^S ^[[38;5;046m8^[[0m M-BM-0C^[[0m       $

which renders like this:

Rendered output from wttr.in

Because of this, we can't just extract everything from the first number on, because that would include almost the whole line due to the escape sequences.

Fortunately, we can tell wttr.in to not send us the colour escapes using the T query string parameter (hat tip to keheliya for pointing this out):

$ curl -s wttr.in/Amsterdam?T | grep -m 1 '°.' | cat -A  _ /"".-.     5-8 M-BM-0C         $

Now we can extract everything from the first digit encountered on, using grep -o (retains only the match). This also takes into account that there could be a minus sign for negative temperatures:

curl -s wttr.in/Amsterdam?T | grep -m 1 '°.' | grep -Eo -e '-?[[:digit:]].*'

or, in a single grep expression:

curl -s wttr.in/Amsterdam?T | grep -m 1 -Eo -e '-?[[:digit:]].*°.+'

The output of this is

5–8 °C

Now, if you want just the average if you get a range, you could write a function like this:

cur_temp () {    # Get current temperature into variable    local cur=$(curl -s wttr.in/Amsterdam?T \        | grep -m 1 -Eo -e '-?[[:digit:]].*°.')    # Check if it is a range    if [[ $cur == *..* ]]; then        # Use regex to extract temperature values        local re='(-?[[:digit:]]+)\.\.([[:digit:]]+).*°(.)'        [[ $cur =~ $re ]]        local lower=${BASH_REMATCH[1]}        local upper=${BASH_REMATCH[2]}        local unit=${BASH_REMATCH[3]}        # Calculate average (truncates to integers)        cur="$(( (lower + upper) / 2 )) °$unit"    fi    echo "$cur"}

If we call this function on a result that previously returned a range, we just get the average now (truncated to integers):

$ cur_temp6 °C

Non-ranges are the same as before.

This can be parameterized for location, just like in the example function that you get from wttr.in/:bash.function.


I could add Temp, H, P and Wind with this simple line at my i3block:

[weather]full_text=command=curl wttr.in/-31.82,-60.52\?format\="%t%20|%20%h%20|%20%P%20|%20%w"interval=1800

It's a spartan beauty:

wttr_i3Blocks image