1

Тема: Довгий sed, чи shell скрипт з case'ом ?

Здорів.
Є сервіс wttr.in, що показує погоду.
Якщо додати ось такі параметри wttr.in/?0&T&Q, то воно покаже погоду на даний час ось в такому форматі

  _`/"".-.     Місцями дощ
   ,\_(   ).   16 °C          
    /(___(__)  → 23 km/h      
      ‘ ‘ ‘ ‘  16 km          
     ‘ ‘ ‘ ‘   0.2 mm         

Завдання: Я хочу трансформувати цю інформацію ось в такий формат

іконка_що_показує_стан_погоди температура напрямок_вітру сила_вітру

Я можу отримати майже те, що мені потрібно, ось такою командою

curl -sS "https://wttr.in?0&T&Q" | cut -c 16- | head -3 | xargs echo

Єдине, що мені ще треба - це замінити текстову репрезентацію стану погоди на іконку.
Список можливих станів ось туто https://github.com/chubin/wttr.in/blob/ … ons/uk.txt

Питання: як краще організувати заміну, через купу sed'ів, типу

curl -sS "https://wttr.in?0&T&Q" | cut -c 16- | head -3 | xargs echo | sed "s/Patchy rain possible/icon/; s/Clear/icon1/; ..."

(це для кожного стану погоди треба написати "s/назва стану погоди/іконка/")

Або написати скрипта, котрий би то все через case робив?

Як би ви зробили?

Подякували: leofun01, ReAl, Chemist-i, P.Y.4

2

Re: Довгий sed, чи shell скрипт з case'ом ?

Як на мене, то заміна xargs разом із sed на

awk -e 'BEGIN { icons["Partly cloudy"]="icon1"; icons["Patchy rain possible"]="icon2"} NR==1{ printf "%s", icons[$0] } NR!=1{printf " %s", $0}'

дещо естетичніша.

Подякували: FakiNyan1

3

Re: Довгий sed, чи shell скрипт з case'ом ?

я просто не дуже файно знаю awk, тре буде почитати про нього більше

4

Re: Довгий sed, чи shell скрипт з case'ом ?

BEGIN { } виконується перед обробкою всього файлу, там я асоціативний масив на два записи зробив, треба на всі
Далі оброблюється кожен «record» (виділяються про RS, за умовчанням порядково).
NR містить номер «запису»-рядка.

BEGIN там — спец-мітка блоку коду (ще є END, після останнього запису)
Далі ще два блоки з мітками NR==1 (для першого запису) і NR!=1 (для всіх інших)
Мітки можуть бути регекспами для запису.

$0 це весь запис, а $1 і далі то він побитий на поля по FS (див. той лінк). Тобто для третього запису $2 це буде число швидкості вітру

Подякували: FakiNyan, leofun012

5

Re: Довгий sed, чи shell скрипт з case'ом ?

думав, зараз швидко гляну два-три туторіали по awk і все буду знати про нього, але ні. Знайшов книжку, 500 з чимось сторінок...

6

Re: Довгий sed, чи shell скрипт з case'ом ?

ReAl написав:

Як на мене, то заміна xargs разом із sed на

awk -e 'BEGIN { icons["Partly cloudy"]="icon1"; icons["Patchy rain possible"]="icon2"} NR==1{ printf "%s", icons[$0] } NR!=1{printf " %s", $0}'

дещо естетичніша.

щось не дуже ця команда працює

7

Re: Довгий sed, чи shell скрипт з case'ом ?

перевірив ось на цьому файлику

Clear
Sunny
Partly cloudy
Cloudy
Overcast
Mist
Patchy rain possible
Patchy snow possible
Patchy sleet possible
Patchy freezing drizzle possible
Thundery outbreaks possible
Blowing snow
Blizzard
Fog
Freezing fog
Patchy light drizzle
Light drizzle
Freezing drizzle
Heavy freezing drizzle
Patchy light rain
Light rain
Moderate rain at times
Moderate rain
Heavy rain at times
Heavy rain
Light freezing rain
Moderate or heavy freezing rain
Light sleet
Moderate or heavy sleet
Patchy light snow
Light snow
Patchy moderate snow
Moderate snow
Patchy heavy snow
Heavy snow
Ice pellets
Light rain shower
Moderate or heavy rain shower
Torrential rain shower
Light sleet showers
Moderate or heavy sleet showers
Light snow showers
Moderate or heavy snow showers
Patchy light rain with thunder
Moderate or heavy rain with thunder
Patchy light snow with thunder
Moderate or heavy snow with thunder

в обробленому рядку не було згадки про icon1

8

Re: Довгий sed, чи shell скрипт з case'ом ?

о. я тут придумав. Я ж можу просто зробити файлик типу "Назва стану погоди : символ", а потім якоюсь командою то все спарсити. Так буде навіть простіше

9

Re: Довгий sed, чи shell скрипт з case'ом ?

типу тако

cat file | grep "Clear:" | cut -d ":" -f2

і готово, отримали потрібну іконку

10 Востаннє редагувалося ReAl (04.05.2019 15:15:22)

Re: Довгий sed, чи shell скрипт з case'ом ?

FakiNyan написав:

перевірив ось на цьому файлику

в обробленому рядку не було згадки про icon1

Сайт видає всі оті «Patchy...» у першому рядку відповіді, а той скрипт для awk розрахований на парсинг конкретного формату відповіді. Якщо там замість NR!=1 написати NR==2 || NR==3, то там і head -3 стане непотрібним, усі рядки окрім 1 для іконок та 2 і 3 для просто друку воно проігнорує:

$ curl -sS "https://wttr.in?0&T&Q" | cut -c 16- | awk -e 'BEGIN { icons["Partly cloudy"]="icon1"; } NR==1{ printf "%s", icons[$0] } NR==2 || NR==3 {printf " %s", $0}'
icon1 -5..-4 °C       ↗ 4 km/h

(мою локацію не бачить, відповідає на дефолтну Partly cloudy, під це підбив рядок)

Подякували: FakiNyan1

11 Востаннє редагувалося FakiNyan (04.05.2019 21:12:23)

Re: Довгий sed, чи shell скрипт з case'ом ?

коротше, вирішив я робити по-своєму, бо я в тому авк не розбираюся, і якщо треба буде щось модифіковувати, або додавати - то я сам не зможу то зробити
Мучався пів дня.
https://i.imgur.com/7YXnnRI.png

як бачите, я ще додав розмалювання в залежності від температури, та сили вітру. Ну і самим іконкам теж додав кольори

Ось весь код, але я попереджую - вагітним та зі слабкою психікою перегляд заборонено!

Прихований текст
#!/bin/bash

res=$(curl -sS "http://wttr.in?0&T&Q" | cut -c 16- | head -3)
digits=$(echo "$res" | grep -Po "\d+")
temp=$(echo "$digits" | awk 'FNR==1{ print }')
wind=$(echo "$digits" | awk 'FNR==2{ print }')

if [ "$temp" -lt 0 ]
then
    temp=$("<span color=\"#4286f4\">$temp °C<\/span>")
elif [ "$temp" -lt 10 ]
then
    temp=$("<span color=\"#e2e2e2\">$temp °C<\/span>")
elif [ "$temp" -lt 15 ]
then
    temp="<span color=\"#fafcd6\">${temp} °C<\/span>"
elif [ "$temp" -lt 20 ]
then
    temp="<span color=\"#ffd77c\">${temp} °C<\/span>"
elif [ "$temp" -lt 25 ]
then
    temp=$("<span color=\"#ffbb4f\">$temp °C<\/span>")
elif [ "$temp" -lt 30 ]
then
    temp=$("<span color=\"#ff9d00\">$temp °C<\/span>")
else 
    temp=$("<span color=\"#ff6a00\">$temp °C<\/span>")
fi

if [ "$wind" -lt 5 ]
then
    wind=$("<span color=\"#42f448\">$wind km\/h<\/span>")
elif [ "$wind" -lt 12 ]
then
    wind="<span color=\"#d9ff00\">${wind} km\/h<\/span>"
elif [ "$wind" -lt 19 ]
then
    wind=$("<span color=\"#ffbb00\">$wind km\/h<\/span>")
elif [ "$wind" -lt 36 ]
then
    wind="<span color=\"#ff7f00\">${wind} km\/h<\/span>"
elif [ "$wind" -lt 50 ]
then
    wind=$("<span color=\"#ff4300\">$wind km\/h<\/span>")
elif [ "$wind" -lt 72 ]
then
    wind=$("<span color=\"#ff9d00\">$wind km\/h<\/span>")
else 
    wind=$("<span color=\"red\">$wind km\/h<\/span>")
fi

while IFS= read -r line; do
    text=$(echo "$line" | cut -d ":" -f1)
    icon=$(echo "$line" | cut -d ":" -f2)
    res=$(echo $res | sed -e "s/^$text \([0-9]\+\)/$icon \1/")
done < "/usr/local/i3blocks/forecast_icons"

res=$(echo $res | sed "s/\([0-9]\+\) °C/$temp/; s/\([0-9]\+\) km\/h/$wind/")

echo $res

файлик з іконками в форматі

Sunny:<span color="yellow">Іконка<\/span>

Особливо мені сподобались регекси, коли потрібно ескапіювати слеши. То виходило щось типу

s/km\/h/km\\\//h/

12 Востаннє редагувалося leofun01 (05.05.2019 18:55:20)

Re: Довгий sed, чи shell скрипт з case'ом ?

Я не зміг на то спокійно дивитися

#!/bin/bash

res=$(curl -sS "http://wttr.in?0&T&Q" | cut -c 16- | head -3)
digits=$(echo "$res" | grep -Po "\d+")
temp=$(echo "$digits" | awk 'FNR==1{ print }')
wind=$(echo "$digits" | awk 'FNR==2{ print }')

color="#ffffff"
if   [ "$temp" -lt  0 ]; then color="#4286f4"
elif [ "$temp" -lt 10 ]; then color="#e2e2e2"
elif [ "$temp" -lt 15 ]; then color="#fafcd6"
elif [ "$temp" -lt 20 ]; then color="#ffd77c"
elif [ "$temp" -lt 25 ]; then color="#ffbb4f"
elif [ "$temp" -lt 30 ]; then color="#ff9d00"
else                          color="#ff6a00"
fi
temp="<span color=\"${color}\">${temp} °C<\/span>"

color="#ffffff"
if   [ "$wind" -lt  5 ]; then color="#42f448"
elif [ "$wind" -lt 12 ]; then color="#d9ff00"
elif [ "$wind" -lt 19 ]; then color="#ffbb00"
elif [ "$wind" -lt 36 ]; then color="#ff7f00"
elif [ "$wind" -lt 50 ]; then color="#ff4300"
elif [ "$wind" -lt 72 ]; then color="#ff9d00"
else                          color="red"
fi
wind="<span color=\"${color}\">${wind} km\/h<\/span>"

while IFS= read -r line; do
    text=$(echo "$line" | cut -d ":" -f1)
    icon=$(echo "$line" | cut -d ":" -f2)
    res=$(echo $res | sed -e "s/^$text \([0-9]\+\)/$icon \1/")
done < "/usr/local/i3blocks/forecast_icons"

res=$(echo $res | sed "s/\([0-9]\+\) °C/$temp/; s/\([0-9]\+\) km\/h/$wind/")

echo $res
Подякували: FakiNyan1

13

Re: Довгий sed, чи shell скрипт з case'ом ?

FakiNyan написав:

Особливо мені сподобались регекси, коли потрібно ескапіювати слеші. То виходило щось типу

s/km\/h/km\\\//h/

SED дозволяє замість слешів використовувати довільні символи, щоб зайвий раз не ескейпити їх:

s!km/h!km\\//h!

(чи що там малось на увазі)

Подякували: FakiNyan1

14

Re: Довгий sed, чи shell скрипт з case'ом ?

leofun01, до речі, у вас там синтаксис неправильний, then має бути з нового рядка

Подякували: leofun011

15

Re: Довгий sed, чи shell скрипт з case'ом ?

FakiNyan написав:

там синтаксис неправильний, then має бути з нового рядка

Я оновив код, доставив ; . Тепер має працювати.

Подякували: FakiNyan1