[script] Les news dans le terminal (résolu)

Autres projets et contributions
avi3000
Chu Ko Nu
Messages : 386
Inscription : dim. 19 juin 2011, 18:53
Localisation : dans le neuf trois

Re: [script] Les news dans le terminal (résolu)

Message par avi3000 » jeu. 17 juil. 2014, 22:15

benjarobin a écrit :Elle est peut être légèrement plus simple, mais ne fait même pas 1% de l'autre...
Excellente contribution, éminemment constructive.
Il me semblait que le formatage multi-lignes, qu'il soit fait en sed ou awk, représentait 99% de l'intérêt des scripts.
Mais si l'essentiel est d'ajouter 2 séquences d'échappement et un bout de replace, il y a quelque chose qui m'échappe.

Puisqu'il faut tout coder, à la virgule près, les 2 scripts ci-dessous devraient convenir.

testnews.sh

Code : Tout sélectionner

#!/bin/sh
sed_news () {
     echo -e "\n \\e[01;31m\t\t >> News Archlinux.fr << \\e[00m\n$(
     curl -s https://archlinux.fr/feed | sed '/<title\|<pubDate/!d;s/\t*//g;s/<\/*title>/ - /g;s/[0-9]*:.*/\\e[00m/g;s/&#8217;/'"'"'/g;s/&#8211;/-/g;/Archlinux.fr/d' |
     sed 'N;s/\n<pubDate>/\\033[1;34m/g;P;D;') \n"
}    

awk_news () {
     curl https://archlinux.fr/feed -s |
     awk 'BEGIN {red="\033[1;31m"; bleu="\033[34m"; defo="\033[0m"; print red"\n\t\t>> News Archlinux.fr <<"defo} /<title>/ {z=substr($0,10,length($0)-17)}
           /<pubDate>/ {gsub("&#8217;", "\x27", z); print z "||" bleu $2" " $3 " " $4 defo}'
}

alias ak_news='curl https://archlinux.fr/feed -s | 
      awk '"'"' BEGIN {red="\033[31m"; bleu="\033[34m"; defo="\033[0m"; print red"\n\t\t>> News Archlinux.fr <<"defo}
           /<title>/ {z=substr($0,10,length($0)-17)}  /<pubDate>/ {gsub("&#8217;", "\x27", z);print z "||" bleu $2" " $3 " " $4 defo}'"'"
waitnsea a écrit :Effectivement la commande est plus simple et tout à fait efficace, mais elle ne se laisse pas transformer en alias
Mauvaise approche, ce n'est pas parce qu'on ne sait pas que ça ne le fait pas (alias ak_news 1er script)
waitnsea a écrit :elle est plus rapide aussi (l'initiale)...
A-tu fais des tests ?
Pour avoir tester les 2 deux, les temps de réponse sont du même ordre : quelques millisecondes d'écart sur un i5.
Le temps de latence n'est pas au même endroit, avant l'affichage de ">> News Archlinux.fr <<" dans un cas, après dans l'autre ce qui explique ton impression.


Pour des choses un tant soit peu complexes, Awk me parait plus clair et plus maintenable que Sed, surtout si on n'utilise celui-ci qu'occasionnellement (avis personnel)
Le 2ème script s'utilise ainsi : curl -s https://archlinux.fr/feed | ./awknews

awknews

Code : Tout sélectionner

#!/usr/bin/awk -f
BEGIN {
     red="\033[31m"
     bleu="\033[34m"
     defo="\033[0m"
     print red "\n\t\t>> News Archlinux.fr <<" defo
}
/<title>/ {
     z=substr($0,10,length($0)-17)
}
/<pubDate>/ {
     gsub("&#8217;", "\x27", z)
     print z "||" bleu $2" " $3 " " $4 defo
}

Avatar de l’utilisateur
waitnsea
Maître du Kyudo
Messages : 2046
Inscription : jeu. 15 mars 2012, 05:08

Re: [script] Les news dans le terminal (résolu)

Message par waitnsea » ven. 18 juil. 2014, 11:26

Merci avi3000,
J'ai beaucoup à apprendre...

4nti7rust
Hankyu
Messages : 34
Inscription : dim. 13 nov. 2011, 15:22

Re: [script] Les news dans le terminal (résolu)

Message par 4nti7rust » ven. 18 juil. 2014, 22:37

Salut,

Je pensais être le seul utilisateur de cet horrible UBER-regex-rss-parser tueur de chatons ... Mais il semblerait que certains en redemandent.

Voici donc la version que j'utilise actuellement :

Code : Tout sélectionner

echo -e "\n\\e[01;31m> News Archlinux.fr\\e[00m\n$(curl -s https://archlinux.fr/feed | sed '/<title\|<pubDate/!d;s/\t*//g;s/<title>/ - /g;s/<\/title>//g;s/ [0-9]* [0-9]*:.*/\\e[00m/g;s/&#8217;/'"'"'/g;s/&#8211;//g;/Archlinux.fr/d;s/intervention manuelle/\\033[1;33mintervention manuelle\\e[00m/g;' | sed 'N;s/\n<pubDate>/ - \\033[1;34m/g;P;D;') \n"
Je pense que le script de avi3000 est bien mieux. J’hésite à faire une version php histoire d'utiliser un vrai parseur.

[EDIT] Script de avi3000 modifié pour obtenir le même résultat qu'avec la version sed :

Code : Tout sélectionner

#!/usr/bin/awk -f
BEGIN {
     red="\033[1;31m"
     bleu="\033[1;34m"
     defo="\033[0m"
     jaun="\033[1;33m"
     print red "\n> News Archlinux.fr" defo
}
/<title>/ {
    z=substr($0,10,length($0)-17)
    gsub("intervention manuelle", jaun "intervention manuelle" defo, z)
}
/<pubDate>/ {
     gsub("&#8217;", "\x27", z)
     print " - " z " - " bleu $2" " $3 " " $4 defo
}

avi3000
Chu Ko Nu
Messages : 386
Inscription : dim. 19 juin 2011, 18:53
Localisation : dans le neuf trois

Re: [script] Les news dans le terminal (résolu)

Message par avi3000 » sam. 19 juil. 2014, 00:03

Je vois qu'on a envie de se lancer dans le codage récréatif.

une version bash, pour varier les plaisirs: curl -s https://archlinux.fr/feed | ./sh_news

sh_news

Code : Tout sélectionner

#!/bin/sh
red="\033[31m"
bleu="\033[34m"
defo="\033[0m"
on_one="$red \n\t\t>> News Archlinux.fr <<$defo"

while read z; do
     [ "${z:0:7}" = '<title>' ] && {
	  z=${z//&#8216;/\\x27}
	  z=${z//&#8217;/\\x27}
          z=${z//&#8211;/-}
	  z=${z//&gt;/>}
           [ "$on_one" = '' ] && echo -en "${z:7:-8}" || echo -e "$on_one"
          on_one=''
     }   
     [ "${z:0:9}" = '<pubDate>' ] && {
          echo -e " || $bleu${z:14:-25}$defo"
     }   
done
echo
un autre méthode (printf) avec awk permettant de déplacer le temps d'attente :
awknews2

Code : Tout sélectionner

#!/usr/bin/awk -f
BEGIN {
     red="\033[31m"
     bleu="\033[34m"
     defo="\033[0m"
     on_one=red "\n\t\t>> News Archlinux.fr <<" defo
}

/<title>/ {
     if ( on_one ) { 
          print(on_one)
          on_one=""
     }   
     else
          printf(gensub("&#8217;", "\x27", "g", substr($0,10,length($0)-17)))
}

/<pubDate>/ {
     print("||" bleu $2" " $3 " " $4 defo)
}
J'ai fait quelques tests de temps de réponse avec un fichier local.
Les versions awk sont 2 fois plus rapides que la version sed (normal 2 appels sed, 1 appel awk) et 3 fois plus rapides que la version bash.

Il existe un vrai parser xml pour awk : getXMLEVENT.awk.
Mais son usage n'est pas nécessaire pour des cas simples comme ce fil de nouvelles.
Dernière modification par avi3000 le dim. 17 nov. 2019, 19:07, modifié 2 fois.

avi3000
Chu Ko Nu
Messages : 386
Inscription : dim. 19 juin 2011, 18:53
Localisation : dans le neuf trois

Re: [script] Les news dans le terminal (résolu)

Message par avi3000 » dim. 20 juil. 2014, 11:57

la version python3: curl -s https://archlinux.fr/feed | ./news.py

news.py

Code : Tout sélectionner

#!/usr/bin/env python

import sys 

red  = "\033[31m"
bleu = "\033[34m"
defo = "\033[0m"
buf = False

xml = sys.stdin.read().splitlines()
for z in xml :
    z = z.lstrip()
    if z[0:7] == "<title>" : 
        if buf :
            buf += '\n' + z[7:-8].replace('&#8217;', 'ʼ') + ' || '
        else :
            buf = red + "\n\t\t>> News Archlinux.fr <<" + defo
    elif z[0:9] == "<pubDate>" : 
        buf += bleu + z[14:-25] + defo

print(buf)
la version script C : curl -s https://archlinux.fr/feed | ./news.c(pacman -S tcc, si ce n'est pas déjà fait)

news.c

Code : Tout sélectionner

#!/usr/bin/tcc -run            
                               
#include <stdio.h>             
#include <string.h>
  
#define MAX_LINE_SIZE   1024   
#define RED             "\033[31m"
#define BLEU            "\033[34m"
#define DEFO            "\033[0m"
  
int main() {                   
    char line[MAX_LINE_SIZE];  
    char buf[MAX_LINE_SIZE];  
    char *z, *y;               
    int on_one = 1;            
       
    while ( fgets(line, MAX_LINE_SIZE, stdin) ) {
        if ( z = strstr(line, "<title>") ) { 
            if ( on_one ) {
                printf("%s\n\t\t>> News Archlinux.fr <<%s\n", RED, DEFO);
                on_one = 0;
            }
            else {
                z[strlen(z)-9] = '\0';          
                while ( y = strstr(z, "&#8217;") ) {
                    y[0] = '\'';                    
                    strcpy(buf, y+7);   
                    strcpy(y+1, buf);
                }
                printf("%s", z+7);              
            }
        }
        else if ( z = strstr(line, "<pubDate>") ) { 
            z[strlen(z)-26] = '\0';         
            printf(" || %s%s%s\n", BLEU, z+14, DEFO);
        }
    }
    return 0;
}
la version sed améliorée : echo -e "\n$(curl -s https://archlinux.fr/feed | ./sednews2)\n"

sednews2

Code : Tout sélectionner

#!/usr/bin/sed -f 
/<title\|<pubDate\|<rss /!d;
s/\t*//g;

/<rss /  {
     s/.*/\t\t\\e[31m>> News Archlinux.fr <<\\e[0m/
}
/<title>/  {
     s,</*title>, - ,g
     s/&#8217;/’/g
     h   
     D   
}
/<pubDate>/ {
     s/^.\{14\}\(.\{11\}\).*$/\\e[34m\1\\e[0m/
     H   
     g   
     s/\n//;
}
Temps de réponse ( boucle de 100 sur un fichier local ) :

Code : Tout sélectionner

le script C compilé       0.12s
le script C interprété    0.30s
le script awknews2        0.40s
le script sednews2        0.40s
la version sed de base    0.70s
le script bash sh_news    1.05s
le script python news.py  1.65s
je vous laisse le soin de coder les versions, ruby, perl, php, java, ...

avi3000
Chu Ko Nu
Messages : 386
Inscription : dim. 19 juin 2011, 18:53
Localisation : dans le neuf trois

Re: [script] Les news dans le terminal (résolu)

Message par avi3000 » lun. 18 nov. 2019, 12:23

Une version bash 2019.
Le lien peut être passé en paramètre.

Code : Tout sélectionner

#!/bin/bash

red="\033[31m"
bleu="\033[34m"
defo="\033[0m"
on_one="\n\t\t>> News Archlinux.fr <<$defo"

while read z; do
     [ "${z:0:7}" = '<title>' ] && {
          z=${z//&#8216;/\\x27}
          z=${z//&#8217;/\\x27}
          z=${z//&#8211;/-}
          z=${z//&gt;/>}
          [ "$on_one" = '' ] && titre=${z:7:-8} || echo -e "$red$on_one"
          on_one=''
     }
     [ "${z:0:9}" = '<pubDate>' ] && {
          echo -e "$bleu${z:14:-25}$defo  $titre"
     }
done < <(curl -s ${@:-https://archlinux.fr/feed})
echo

Avatar de l’utilisateur
waitnsea
Maître du Kyudo
Messages : 2046
Inscription : jeu. 15 mars 2012, 05:08

Re: [script] Les news dans le terminal (résolu)

Message par waitnsea » lun. 18 nov. 2019, 16:54

avi3000 a écrit :
lun. 18 nov. 2019, 12:23
Une version bash 2019.
Merci de la mise à jour...Impeccable.
Sans être exigeant ni critique, car je m'en accommode fort bien depuis 5 ans, y-a-t’il moyen de corriger la mauvaise prise en charge des accentués :

Code : Tout sélectionner

...Remplacement du groupe &#8216;base’...
 La mise à jour de astyle&gt;=3.1-2

laurent85
Elfe
Messages : 585
Inscription : mar. 16 oct. 2018, 21:05

Re: [script] Les news dans le terminal (résolu)

Message par laurent85 » lun. 18 nov. 2019, 18:07

Bonjour,
Tu dois avoir un pb de locale moi l'affichage est impeccable en console et xorg.
Tuto Kde Plasma + gestionnaire de fenêtres i3
Mon développement en cours Archuseriso

avi3000
Chu Ko Nu
Messages : 386
Inscription : dim. 19 juin 2011, 18:53
Localisation : dans le neuf trois

Re: [script] Les news dans le terminal (résolu)

Message par avi3000 » lun. 18 nov. 2019, 18:26

waitnsea a écrit :
lun. 18 nov. 2019, 16:54
Sans être exigeant ni critique, car je m'en accommode fort bien depuis 5 ans, y-a-t’il moyen de corriger la mauvaise prise en charge des accentués :

Code : Tout sélectionner

...Remplacement du groupe &#8216;base’...
 La mise à jour de astyle&gt;=3.1-2
Il faut bien tout lire moet hennesy. C'était corrigé dans la version bash 2019.
Pour les autre versions, à chacun de se démerder, c'est comme ça qu'on apprend.

Avatar de l’utilisateur
waitnsea
Maître du Kyudo
Messages : 2046
Inscription : jeu. 15 mars 2012, 05:08

Re: [script] Les news dans le terminal (résolu)

Message par waitnsea » lun. 18 nov. 2019, 19:07

@ laurent85 - Non mes locales sont OK, merci
@avi3000 - J'avais bien lu mais mal tapé mes commandes de copie dans vim et gardé la vieille version...! le cru 2019 est effectivement sans erreur, merci aussi

sukolyn
archer
Messages : 106
Inscription : mar. 11 juil. 2017, 09:56

Re: [script] Les news dans le terminal (résolu)

Message par sukolyn » lun. 18 nov. 2019, 23:11

Code : Tout sélectionner

wget -qO - archlinux.fr/feed \
   | xmlstarlet sel -D --net -E 'utf-8' -T -t -m '//channel/item' -n -v 'pubDate' -n -o '^[[01m' -v 'title' -o '^[[0m' -n -v 'description' -n - \
   | sed 's/&#8217;/'\''/g; s/&#8230;/.../g'
--
edit:
^[ est obtenu en tapant Ctrl-v-[

avi3000
Chu Ko Nu
Messages : 386
Inscription : dim. 19 juin 2011, 18:53
Localisation : dans le neuf trois

Re: [script] Les news dans le terminal (résolu)

Message par avi3000 » mar. 19 nov. 2019, 19:21

@sukolyn
ta solution n'est pas terrible:
tu remplace bash + un sous-shell curl par 3 processus wget + xmlstarlet + sed.

c'est un process de trop.
et un paquet supplémentaire à installer.

un version plus complète

Code : Tout sélectionner

#!/bin/bash

red="\033[31m"
bleu="\033[34m"
defo="\033[0m"
on_one="\n\t\t>> News Archlinux.fr <<$defo"

parse_z () {
    z=${z//&#8216;/\\x27}
    z=${z//&#8217;/\\x27}
    z=${z//&#8211;/-}
    z=${z//&#8230;/...}
    z=${z//&gt;/>}
}

while read z; do
    [ "${z:0:7}" = '<title>' ] && {
        parse_z
        [ "$on_one" = '' ] && titre=${z:7:-8} || echo -e "$red$on_one"
        on_one=''
    }
    [ "${z:0:9}" = '<pubDate>' ] && {
        echo -e "$bleu${z:14:-25}$defo  $titre"
    }
    [ "${z:0:14}" = '<description><' ] && {
        z=${z#*A[}
        z=${z%]]>*}
        parse_z
        echo -e "$z\n"
    }
done < <(curl -s ${@:-https://archlinux.fr/feed})
echo

# vim: ts=4 sw=4 :

sukolyn
archer
Messages : 106
Inscription : mar. 11 juil. 2017, 09:56

Re: [script] Les news dans le terminal (résolu)

Message par sukolyn » mar. 19 nov. 2019, 22:05

mais pourquoi parfois y a-t-il par exemple des apostrophes, et parfois une "entité" HTML (#&8217;) ?

avi3000
Chu Ko Nu
Messages : 386
Inscription : dim. 19 juin 2011, 18:53
Localisation : dans le neuf trois

Re: [script] Les news dans le terminal (résolu)

Message par avi3000 » mar. 19 nov. 2019, 23:40

parce que la vie n'est pas facile et le rédacteur de news est taquin.

sukolyn
archer
Messages : 106
Inscription : mar. 11 juil. 2017, 09:56

Re: [script] Les news dans le terminal (résolu)

Message par sukolyn » mer. 20 nov. 2019, 00:53

une autre expression me vient à l'esprit, qui s'allitère plutôt bien à "est taquin", mais bon.

je préférerais un case/esac à ces tests.

sukolyn
archer
Messages : 106
Inscription : mar. 11 juil. 2017, 09:56

Re: [script] Les news dans le terminal (résolu)

Message par sukolyn » mer. 20 nov. 2019, 03:09

Code : Tout sélectionner

#!/usr/bin/python

import requests # il faut installer python-requests. ça ira ?
from xml.etree import ElementTree as ET
import textwrap

news = requests.get('https://archlinux.fr/feed')
root = ET.fromstring(news.text)

for t in root.findall("channel/item"):
    title = t.find('title').text
    date = t.find('pubDate').text
    desc = t.find('description').text
    desc = desc.replace('&#8230;','...')
    desc = desc.replace('&#8217;',"'")
    desc = desc.replace('&#8216;',"'")
    desc = desc.replace('&#8211;',"-")
    desc = textwrap.fill(desc,80)
    print("%s\n\033[01;31m%s\n\033[00;36m%s\033[00m\n"%(date, title, desc))

Avatar de l’utilisateur
waitnsea
Maître du Kyudo
Messages : 2046
Inscription : jeu. 15 mars 2012, 05:08

Re: [script] Les news dans le terminal (résolu)

Message par waitnsea » mer. 20 nov. 2019, 05:39

Et que c'est beau en plus ! :shock: :bravo:

sukolyn
archer
Messages : 106
Inscription : mar. 11 juil. 2017, 09:56

Re: [script] Les news dans le terminal (résolu)

Message par sukolyn » mer. 20 nov. 2019, 11:54

j'ai récupéré une fonction pour éviter la succession de replace() qui ne me plaît pas :

Code : Tout sélectionner

#!/usr/bin/python

import requests
from xml.etree import ElementTree as ET
import textwrap

def replace_all(text, dico):
    for i, j in dico.items():
        text = text.replace(i, j)
    return text

entities = { '&#8230;': '...', '&#8216;': "'", '&#8217;': "'", '&#8211;': '-' }
 
news = requests.get('https://archlinux.fr/feed')
root = ET.fromstring(news.text)

for t in root.findall("channel/item"):
	title = t.find('title').text
	date = t.find('pubDate').text
	desc = replace_all(t.find('description').text , entities)
	print("%s\n\033[01;31m%s\n\033[00;36m%s\033[00m\n"%(date, title, textwrap.fill(desc,100)))
ainsi, seul le dictionnaire s'allonge à mesure qu'on rencontre des "entités" à convertir.

avi3000
Chu Ko Nu
Messages : 386
Inscription : dim. 19 juin 2011, 18:53
Localisation : dans le neuf trois

Re: [script] Les news dans le terminal (résolu)

Message par avi3000 » mer. 20 nov. 2019, 13:13

Un petit concours de code !!

@sukolyn il faut installer python-requests. ça ira ?
Non, 9 paquets et 5,40Mo installé pour traiter 3 noeuds, c'est prendre un marteau pour écraser une mouche.

Code : Tout sélectionner

pacman -S python-requests
résolution des dépendances…
recherche des conflits entre paquets…

Paquets (9) python-appdirs-1.4.3-5  python-chardet-3.0.4-4  python-idna-2.8-3  python-packaging-19.2-5  python-pyparsing-2.4.5-1  python-setuptools-1:41.2.0-5  python-six-1.13.0-2  python-urllib3-1.25.7-1  python-requests-2.22.0-3

Taille totale du téléchargement :  0,92 MiB
Taille totale installée :        5,40 MiB
J'avais fait des tests comparatifs ici.
python3 est toujours le moins performant.

J'ai refait des tests avec tes versions sur un fichier local. Les résultats sont encore sans appel.
Modifications pour traiter le fichier local (j'ai également supprimer le textwrap pour comparer le même traitement)

Code : Tout sélectionner

#!/usr/bin/python

def replace_all(text, dico):
    for i, j in dico.items():
        text = text.replace(i, j)
    return text

entities = { '&#8230;': '...', '&#8216;': "'", '&#8217;': "'", '&#8211;': '-' }

from lxml.etree import parse as ET
root = ET('./feed')

for t in root.findall("channel/item"):
    title = t.find('title').text
    date = t.find('pubDate').text
    desc = replace_all(t.find('description').text , entities)
    print("%s\n\033[01;31m%s\n\033[00;36m%s\033[00m\n"%(date, title, desc))
Les résultats n'ont pas changé

Code : Tout sélectionner

time for (( i=100; i>0; i-- )); do ./news2.py >/dev/null;done
real    0m3,360s  user    0m2,982s  sys     0m0,383s

time for (( i=100; i>0; i-- )); do ./news.py >/dev/null;done
real    0m3,338s  user    0m2,842s  sys     0m0,501s

time for (( i=100; i>0; i-- )); do ./news.sh ./feed >/dev/null;done
real    0m0,841s  user    0m0,619s   sys     0m0,241s

ta version est moins rapide que ma version python de 2014.

Code : Tout sélectionner

time for (( i=100; i>0; i-- )); do cat ./feed | ./mon_python.py >/dev/null;done
real    0m1,242s  user    0m1,106s  sys     0m0,207s
En étant plus proche du pseudo-code, le programme est portable dans beaucoup de langage.
Rapidité d'écriture vs rapidité d'éxécution, mon choix est fait depuis longtemps.
Je pense que le tien aussi.

sukolyn
archer
Messages : 106
Inscription : mar. 11 juil. 2017, 09:56

Re: [script] Les news dans le terminal (résolu)

Message par sukolyn » mer. 20 nov. 2019, 13:56

c'est un peu déstabilisant de voir que bash, qui est réputé être lent, est plus rapide que des outils conçus pour traiter des fichiers d'un format particulier (ici, du XML).

l'intérêt de ces outils est que s'il vient un jour au taquin l'idée de mettre tout le fichier sur une seule ligne, le script sera toujours fonctionnel.

rapidité/stabilité...

Répondre