[Linux] bout de shell: read à la chaine

Marc Chantreux mc@::1
Ven 9 Sep 14:49:00 CEST 2022


salut,

(si jamais ce transfert de discussion gène quelqu'un: n'hésitez pas à le
signaler)

On Fri, Sep 09, 2022 at 11:11:52AM +0200, Thomas Bernard wrote:
> C'est quoi cette syntaxe ? Je comprends que ca met des noms sur les
> arguments passés à la fonction enjoy, est-ce que j'ai bien compris ?

mes excuses: je voulais faire vite un truc générique et vite ...
j'ai fais vite et du coup ça n'est pas lisible parce que
l'intention n'est pas claire.

Aussi: comme j'ai eu plusieurs fois des discussions similaires ces
derniers temps et que le shell est la langue commune un la flamekuche
(avec le français parfois ;)), je me permet de changer de canal pour
continuer la discussion.

Donc en gros: soit un pipe qui envoie des informations ligne par ligne

some_of_my_prefered_movies() <<. cat
Tron	1982	Steven Lisberger
Blade Runner	1982	Ridley Scott
Wargames	1983	John Badham
Le nom de la rose	1986	Jean-Jacques Annaud
The Game	1997 	David Fincher
A Beautiful Mind	2001 	Ron Howard
.
pick() { shuf | sed $1\q | tr '\t' '\n'; }
some_of_my_prefered_movies | pick 1

je veux maintenant pouvoir faire qqchose de ces lignes dans une fonction

some_of_my_prefered_movies | pick 1 | show

show doit lire chacune des infos dans une variable différente. pour
faire propre, il faut donc

* déclarer autant de variables qu'il y a de lignes
* faire autant de read qu'il y a de ligne

la version longue et pas générique:

show() {
	local title year real
	read title
	read year
	read real
	[ $year -lt 2000 ] && >&2 echo "t'es vieux !!!"
	printf '"%s", sorti en %s, a été réalisé par %s\n' \
		"$title" "$year" "$real"
}

la version plus courte

show() {
	local it fields='title year real'
	local $fields # équivalent à local it title year real
	for it in $fields; do read $it; done
}

je peux aussi passer les arguments:

show() {
	local it $@
	for it; do read $it; done
}

sachant que la boucle for parcourt par défaut "$@",
sont parfaitement équivalents:

	for it; do read $it; done
	for it in "$@"; do read $it; done

une version plus générique:
* une fonction qui localise et lit les variables
* faire faire un callback

to() {
	local to_key $with
	while {
		# ce qui est renvoyé ici c'est la valeur du dernier read
		# effectué donc faux quand plus rien à lire
		for to_key in $with; do
			read $to_key
		done
	}; do "$@"; done
}

put it all together et on obtient au choix

with='title year real'
some_of_my_prefered_movies | pick 1 | to show
 
some_of_my_prefered_movies |
	pick 1 | with='title year real' to show


dans mon code initial je ne suis pas allé au bout de ma logique (je n'ai
pas relu mon code par manque de temps)

amitiés,

-- 
Marc Chantreux
Pôle de Calcul et Services Avancés à la Recherche (CESAR)
http://annuaire.unistra.fr/p/20200


Plus d'informations sur la liste de diffusion linux