Contenu | Rechercher | Menus

Annonce

Si vous avez des soucis pour rester connecté, déconnectez-vous puis reconnectez-vous depuis ce lien en cochant la case
Me connecter automatiquement lors de mes prochaines visites.

À propos de l'équipe du forum.

#1 Le 10/12/2017, à 00:54

Arbiel

[cliquer ici pour explications] Ne pas tenter : fic>pipeline>fic

Explication :
La redirection de la sortie standard de la dernière commande d'un tuyau (pipeline) vers le fichier en entrée de la première commande de ce tuyau produit la plupart du temps un fichier vide, mais peut conduire quelque fois à un résultat correct. Ceci s'explique par le fait que chaque commande du tuyau lit son entrée standard au fil de l'écriture par la commande précédente sur sa sortie standard, et donc que la dernière commande peut tenter d'ouvrir en écriture le fichier encore en lecture par la première commande.
Tout dépend de l'activité du PC, et de celle de bash pendant l'exécution du pipeline.

Bonsoir

J'ai créé un fichier qui contient, pour un certain nombre de blocs Unicode, des lignes telles que

:μ:U03BC:ce-bc:mu::Lettre minuscule grecque Mu:greek-coptic:
:ν:U03BD:ce-bd:nu::Lettre minuscule grecque Nu:greek-coptic:
:ξ:U03BE:ce-be:xi::Lettre minuscule grecque Xi:greek-coptic:

dans lesquelles le nom de la page du site web de l'Unicode apparaît en fin de ligne, encadrée de ":".

Dans un script graphique de gestion de ce fichier, je veux aussi bien ajouter de nouveaux blocs ou en retirer. J'utilise yad pour la gestion du dialogue utilisateur.

Il se trouve que l'ajout de blocs fonctionne parfaitement. La suppression, par contre fonctionne de manière aléatoire. Pour localiser le problème j'ai inséré des instruction de contrôle, que je n'ai pas conservées, mais dont j'ai encore la trace de l'exécution.

Je compte d'abord le nombre de lignes du fichier. Il y en a 617. Puis je compte le nombre de lignes à supprimer : 233. Je les supprime et le fichier se retrouve vide :

++ grep -c -e '' /home/.ucg/effectifs/ucg_alphabet
+ x=617
+ y=617
+ y=greek-extended
++ grep -c -e greek-extended /home/.ucg/effectifs/ucg_alphabet
+ x=233
++ grep -c -e :greek-extended: /home/.ucg/effectifs/ucg_alphabet
+ x=233
+ cat /home/.ucg/effectifs/ucg_alphabet
+ sed -r '/greek-extended.$/d'
++ grep -c -e '' /home/.ucg/effectifs/ucg_alphabet
+ x=0
+ y=0

Dans un premier temps, j'utilisais grep avec l'option -v. Avec le même résultat.

Dans un autre essai, j'ai obtenu le résultat cherché

++ grep -c -e '' /home/.ucg/effectifs/ucg_alphabet
+ x=752
+ y=752
+ y=greek-coptic
++ grep -c -e greek-coptic /home/.ucg/effectifs/ucg_alphabet
+ x=135
++ grep -c -e :greek-coptic: /home/.ucg/effectifs/ucg_alphabet
+ x=135
+ cat /home/.ucg/effectifs/ucg_alphabet
+ sed -r '/greek-coptic.$/d'
++ grep -c -e '' /home/.ucg/effectifs/ucg_alphabet
+ x=617
+ y=617

Les 135 lignes du bloc greek-coptic ont correctement été supprimées des 752 lignes initiales, et il en reste bien la différence, 617.
Les conditions d'exécution de ce second test ne sont pas strictement les mêmes, mais j'ai peine à croire que ce soit ici là la raison de cette différence de résultats. Je fais en effet des tests depuis plusieurs jours, le fichier évolue, mais je n'ai constaté aucun lien entre le bloc à supprimer et la destruction du fichier.

J'ai peine à croire que sed et grep ne fonctionnent pas correctement. J'ai l'impression que mon fichier est effacé de manière aléatoire entre le comptage et la tentative de suppression, mais je n'en vois pas la raison.

Pour l'instant je supprime la fonction de suppression des blocs de mon script, mais si quelqu'un avait la moindre idée de ce qui peut se passer, je le remercie par avance de me faire part de ses idées.

Dernière modification par Arbiel (Le 13/12/2017, à 16:36)


Arbiel Perlacremaz
LDLC Aurore NK3S-8-S4 Ubuntu 20.04
Abandon d'azerty au profit de bépo, de google au profit de Lilo et de la messagerie électronique violable au profit de Protonmail, une messagerie chiffrée de poste de travail à poste de travail.

Hors ligne

#2 Le 10/12/2017, à 08:35

pingouinux

Re : [cliquer ici pour explications] Ne pas tenter : fic>pipeline>fic

Bonjour,
Comment utilises-tu sed ? (pour info, le paramètre -r est inutile ici)
La commande suivante ne modifie pas le fichier

sed -r '/greek-coptic.$/d' /home/.ucg/effectifs/ucg_alphabet

mais celle-ci l'efface

sed -r '/greek-coptic.$/d' /home/.ucg/effectifs/ucg_alphabet >/home/.ucg/effectifs/ucg_alphabet

De plus, tu n'utilises pas exactement la même chaîne dans grep et sed.

Hors ligne

#3 Le 10/12/2017, à 13:19

Arbiel

Re : [cliquer ici pour explications] Ne pas tenter : fic>pipeline>fic

Bonjour pingouinux

Je te remercie pour ton intervention.

Je viens de comprendre la raison de mes difficultés, et j'ai fait un test, cette fois positif, avant de revenir sur le forum.

Avec sed, comme antérieurement avec grep, je faisais un pipeline du style

cat /home/.ucg/effectifs/ucg_alphabet | grep -v -e "${filtre}" 1>/home/.ucg/effectifs/ucg_alphabet

ou

cat /home/.ucg/effectifs/ucg_alphabet | sed -r  "/${filtre}.$/d" 1>/home/.ucg/effectifs/ucg_alphabet

et ceci pour éviter d'avoir le fichier en entrée et en sortie de la commande.

J'avais aussi essayer l'option --in-place de sed, qui n'a pas fonctionné pour une autre raison : pour préserver mon fichier, j'en faisais une copie dans /tmp et je montais cette copie sur le fichier. sed ne pouvait alors pas renommer le fichier du fait de ce montage.

Finalement, je suis passé par une variable en mémoire avec

alpha="$(grep -v -e ":${filtre}:" "${alphabet}")";
echo "${alpha}" 1>"${alphabet}" ;

Ce que je faisais revenait donc à ce que tu m'indiques

mais celle-ci l'efface

sed -r '/greek-coptic.$/d' /home/.ucg/effectifs/ucg_alphabet >/home/.ucg/effectifs/ucg_alphabet

Merci encore pour ton aide et tes conseils

Arbiel


Arbiel Perlacremaz
LDLC Aurore NK3S-8-S4 Ubuntu 20.04
Abandon d'azerty au profit de bépo, de google au profit de Lilo et de la messagerie électronique violable au profit de Protonmail, une messagerie chiffrée de poste de travail à poste de travail.

Hors ligne

#4 Le 10/12/2017, à 14:31

Arbiel

Re : [cliquer ici pour explications] Ne pas tenter : fic>pipeline>fic

Ce qui est cependant surprenant, c'est le comportement aléatoire de bash, d'autant plus que les commandes en question, exécutées dans un contexte interactif, fonctionnent correctement.

Par ailleurs, le pipeline, dans la mesure où il permet à une commande de ne pas travailler en entrée et en sortie sur un fichier unique, me semble tout à fait comparable au passage par une variable, la différence entre les deux étant qu'avec le pipeline, la commande travaille sur le contenu de la mémoire pour stoker le résultat dans le fichier, alors qu'avec la variable, la commande travaille sur le fichier pour stocker le résultat dans la mémoire.

Tout cela reste donc pour moi entouré d'un voile mystérieux.

Arbiel


Arbiel Perlacremaz
LDLC Aurore NK3S-8-S4 Ubuntu 20.04
Abandon d'azerty au profit de bépo, de google au profit de Lilo et de la messagerie électronique violable au profit de Protonmail, une messagerie chiffrée de poste de travail à poste de travail.

Hors ligne

#5 Le 10/12/2017, à 15:02

pingouinux

Re : [cliquer ici pour explications] Ne pas tenter : fic>pipeline>fic

Arbiel #4 a écrit :

Ce qui est cependant surprenant, c'est le comportement aléatoire de bash,

Il faudrait voir l'exemple exact pour essayer de le reproduire.

Hors ligne

#6 Le 11/12/2017, à 22:47

Arbiel

Re : [cliquer ici pour explications] Ne pas tenter : fic>pipeline>fic

Bonjour pingouinux

pingouinux a écrit :

Il faudrait voir l'exemple exact pour essayer de le reproduire.

Ce que j'ai laissé du script a pour objectif de gérer un dialogue utilisateur de mise à jour d'un alphabet constitué de caractères définis par des points de code Unicode, eux-mêmes regroupés en sous-ensembles nommés blocs. Le script permet d'ajouter des blocs dans l'alphabet ou de les en retirer.

Les pages html lues sur le site de l'Unicode sont traitées par xmlstarlet.

Le script est un ensemble de fonctions, la procédure principale elle-même étant réduite aux quelques dernières lignes, et en particulier la ligne "${@}" qui permet d'exécuter la commande mentionnée dans la ligne de commande "script commande paramètres".

Le dialogue est traité par yad.

Il présente deux listes de blocs, et une case à cocher pour déterminer si l'action requise porte sur l'une ou l'autre des listes. Je reconnais qu'il serait beaucoup plus simple de ne présenter qu'une seule liste, en marquant les blocs présents dans l'alphabet d'un caractère particulier. Mais c'est là une autre histoire que je traiterai plus tard.

Deux champs, de type BTN, permettent de lancer une commande, en l'occurence la fonction de visualisation de la page du bloc sélectionné dans l'une ou l'autre des deux listes, ou la fonction de gestion de l'alphabet pour l'insertion ou le retrait d'un bloc de points de code. yad n'étant pas "interne" au script, le lancement de ces fonctions se fait par une commande "script commande paramètres", donc dans une incarnation du script différente de celle dans laquelle yad a présenté le dialogue.

Les fichiers créés, le fichier trace et l'alphabet, sont enregistrés l'un dans le répertoire /home/.ucg, l'autre dans le répertoire /home/.ucg/effectif.

J'ai défini une variable globale, "gbl_cas_teste", qui permet de choisir la méthode de retrait d'un bloc, à savoir le passage par une variable (var), ou par un pipeline avec mise à jour par sed ou grep. Pour vérifier que l'effacement du fichier alphabet ne provient pas du changement d'environnement entre les diverses parties d'un pipeline, j'ai activé l'option lastpipe dans le pipeline dont la seconde commande est grep. Cela ne change rien à l'affaire.

Voilà le résultat de mes derniers tests, dans lequel j'ai introduit des commentaires pour rendre l'analyse plus facile. La troisième ligne de chaque essai indique l'ordre dans lequel les blocs sont présents dans l'alphabet.

On peut  y constater que le contexte d'exécution du seul test concluant (le 3) est strictement le même que celui du test non concluant (7). Ou plutôt, je ne vois pas ce qui peut expliquer la différence entre ces deux résultats.

##########################################################
#essai non concluant (1)
#############################################################
++ date
+ echo 'lundi 11 décembre 2017, 21:03:35 (UTC+0100)'
+ echo ':greek-coptic: :basic-latin: :greek-extended: '
++ grep -c -e '' /tmp/.ucg/effectifs/ucg_alphabet
+ x=464
+ x=464
+ x=greek-coptic
++ grep -c -e :greek-coptic: /tmp/.ucg/effectifs/ucg_alphabet
+ x=135
+ x=135
++ grep -c -v -e :greek-coptic: /tmp/.ucg/effectifs/ucg_alphabet
+ x=329
+ x=329
+ case "${gbl_cas_teste}" in
+ shopt -s lastpipe
+ grep -v -e :greek-coptic:
+ cat /tmp/.ucg/effectifs/ucg_alphabet
++ grep -c -e '' /tmp/.ucg/effectifs/ucg_alphabet
+ x=0
+ x=0
+ set +o xtrace
##########################################################
#essai erroné, à ne pas prendre en considération
#############################################################
++ date
+ echo 'lundi 11 décembre 2017, 21:04:42 (UTC+0100)'
+ echo ' '
++ grep -c -e '' /tmp/.ucg/effectifs/ucg_alphabet
+ x=0
+ x=0
+ x=
++ grep -c -e :: /tmp/.ucg/effectifs/ucg_alphabet
+ x=0
+ x=0
++ grep -c -v -e :: /tmp/.ucg/effectifs/ucg_alphabet
+ x=0
+ x=0
+ case "${gbl_cas_teste}" in
+ shopt -s lastpipe
+ grep -v -e ::
+ cat /tmp/.ucg/effectifs/ucg_alphabet
++ grep -c -e '' /tmp/.ucg/effectifs/ucg_alphabet
+ x=0
+ x=0
+ set +o xtrace
##########################################################
#essai non concluant (2)
#############################################################
++ date
+ echo 'lundi 11 décembre 2017, 21:06:29 (UTC+0100)'
+ echo ':greek-coptic: :basic-latin: :greek-extended: '
++ grep -c -e '' /tmp/.ucg/effectifs/ucg_alphabet
+ x=464
+ x=464
+ x=basic-latin
++ grep -c -e :basic-latin: /tmp/.ucg/effectifs/ucg_alphabet
+ x=96
+ x=96
++ grep -c -v -e :basic-latin: /tmp/.ucg/effectifs/ucg_alphabet
+ x=368
+ x=368
+ case "${gbl_cas_teste}" in
+ shopt -s lastpipe
+ grep -v -e :basic-latin:
+ cat /tmp/.ucg/effectifs/ucg_alphabet
++ grep -c -e '' /tmp/.ucg/effectifs/ucg_alphabet
+ x=0
+ x=0
+ set +o xtrace
##########################################################
#essai concluant (3)
#############################################################
++ date
+ echo 'lundi 11 décembre 2017, 21:08:51 (UTC+0100)'
+ echo ':greek-coptic: :basic-latin: :greek-extended: '
++ grep -c -e '' /tmp/.ucg/effectifs/ucg_alphabet
+ x=464
+ x=464
+ x=greek-extended
++ grep -c -e :greek-extended: /tmp/.ucg/effectifs/ucg_alphabet
+ x=233
+ x=233
++ grep -c -v -e :greek-extended: /tmp/.ucg/effectifs/ucg_alphabet
+ x=231
+ x=231
+ case "${gbl_cas_teste}" in
+ shopt -s lastpipe
+ grep -v -e :greek-extended:
+ cat /tmp/.ucg/effectifs/ucg_alphabet
++ grep -c -e '' /tmp/.ucg/effectifs/ucg_alphabet
+ x=231
+ x=231
+ set +o xtrace
##########################################################
#essai non concluant (4)
#############################################################
++ date
+ echo 'lundi 11 décembre 2017, 21:09:45 (UTC+0100)'
+ echo ':greek-coptic: :basic-latin: '
++ grep -c -e '' /tmp/.ucg/effectifs/ucg_alphabet
+ x=231
+ x=231
+ x=basic-latin
++ grep -c -e :basic-latin: /tmp/.ucg/effectifs/ucg_alphabet
+ x=96
+ x=96
++ grep -c -v -e :basic-latin: /tmp/.ucg/effectifs/ucg_alphabet
+ x=135
+ x=135
+ case "${gbl_cas_teste}" in
+ shopt -s lastpipe
+ grep -v -e :basic-latin:
+ cat /tmp/.ucg/effectifs/ucg_alphabet
++ grep -c -e '' /tmp/.ucg/effectifs/ucg_alphabet
+ x=0
+ x=0
+ set +o xtrace
##########################################################
#essai non concluant (5)
#############################################################
++ date
+ echo 'lundi 11 décembre 2017, 21:12:36 (UTC+0100)'
+ echo ':basic-latin: :greek-extended: :greek-coptic: '
++ grep -c -e '' /tmp/.ucg/effectifs/ucg_alphabet
+ x=464
+ x=464
+ x=greek-extended
++ grep -c -e :greek-extended: /tmp/.ucg/effectifs/ucg_alphabet
+ x=233
+ x=233
++ grep -c -v -e :greek-extended: /tmp/.ucg/effectifs/ucg_alphabet
+ x=231
+ x=231
+ case "${gbl_cas_teste}" in
+ shopt -s lastpipe
+ grep -v -e :greek-extended:
+ cat /tmp/.ucg/effectifs/ucg_alphabet
++ grep -c -e '' /tmp/.ucg/effectifs/ucg_alphabet
+ x=0
+ x=0
+ set +o xtrace
##########################################################
#essai non concluant (6)
#############################################################

++ date
+ echo 'lundi 11 décembre 2017, 21:14:36 (UTC+0100)'
+ echo ':basic-latin: :greek-extended: :greek-coptic: '
++ grep -c -e '' /tmp/.ucg/effectifs/ucg_alphabet
+ x=464
+ x=464
+ x=greek-coptic
++ grep -c -e :greek-coptic: /tmp/.ucg/effectifs/ucg_alphabet
+ x=135
+ x=135
++ grep -c -v -e :greek-coptic: /tmp/.ucg/effectifs/ucg_alphabet
+ x=329
+ x=329
+ case "${gbl_cas_teste}" in
+ shopt -s lastpipe
+ grep -v -e :greek-coptic:
+ cat /tmp/.ucg/effectifs/ucg_alphabet
++ grep -c -e '' /tmp/.ucg/effectifs/ucg_alphabet
+ x=0
+ x=0
+ set +o xtrace
##########################################################
#essai non concluant (7)
#############################################################
++ date
+ echo 'lundi 11 décembre 2017, 21:18:25 (UTC+0100)'
+ echo ':greek-coptic: :basic-latin: :greek-extended: '
++ grep -c -e '' /tmp/.ucg/effectifs/ucg_alphabet
+ x=464
+ x=464
+ x=greek-extended
++ grep -c -e :greek-extended: /tmp/.ucg/effectifs/ucg_alphabet
+ x=233
+ x=233
++ grep -c -v -e :greek-extended: /tmp/.ucg/effectifs/ucg_alphabet
+ x=231
+ x=231
+ case "${gbl_cas_teste}" in
+ shopt -s lastpipe
+ grep -v -e :greek-extended:
+ cat /tmp/.ucg/effectifs/ucg_alphabet
++ grep -c -e '' /tmp/.ucg/effectifs/ucg_alphabet
+ x=0
+ x=0
+ set +o xtrace

La fonction "alphabet_retrait" est située entre les lignes 154 et 185. Le dialogue est géré par la fonction "alphabet_creer", située entre les lignes 116 à 140.

Pour exécuter le script, il faut exécuter la commande
"script alphabet_creer".

#! /bin/bash
	function init_gbl {
		gbl_dir_ucg="${UCG_DIR:-"/tmp/.ucg"}";
		gbl_script="${0}";   # nom du script
		gbl_dir_eff="${gbl_dir_ucg}/effectifs" && [[ -d "${gbl_dir_eff}" ]] || mkdir -p "${gbl_dir_eff}" ;
		gbl_web_Unicode="https://unicode-table.com";
		gbl_lg_tlstr="${1:-$(cut -d "_" -f 1 <<< "${LANG}";)}"
		gbl_alphabet="${gbl_dir_eff}/ucg_alphabet";
# cette variable permet de retirer un bloc Unicode soit en passant par une variable, soit par grep soit par sed
		gbl_cas_teste="var"
#		gbl_cas_teste="sed"
		gbl_cas_teste="grep";
	}

############################################################################
# Echo d'une liste de paramètres, chacun précédé de son nom, soit un par ligne, soit en une ligne bash
#############################################################################
	function eb { for _ in "${@}"; do echo -n -e "${_}=\"${!_}\";\t" ; done ; echo; } ;
	function ev { for _ in "${@}"; do declare -p ${_} ; done ; } ;
# lecture d'un fichier ou d'une variable comme première étape d'un pipeline
	function es { [ -f "${1}" ] && cat "${1}" || echo "${1}" ; };
################################################################
# Suppression des lignes commentaires, vides ou ne comportant que des espaces
###########################################################$
	function sup_nul {
		local fic;
		[[ -z "${1}" ]] && fic="/dev/stdin" || fic="${1}";
		grep -v -E "^[[:space:]]*$|^[[:space:]]*#+" < "${fic}";
	}
#############################################################################
# Représentation hexadécimale d'un caractère
#############################################################################$
	function hxdp {
		echo -n "${1}" | xxd -p | gawk '{$1=$1}1' FPAT='.{2}' OFS=- ;
		}
###############################################################
# lecture des pages Unicode
###################################################################
	function lire_web_Unicode {
		local bloc="${1}";
		local type_entit="${2}";
		local lg="${3}";
		local page="${lg}/${type_entit}/${bloc}";
		! [[ -e "${gbl_dir_ucg}/Unicode/${lg}/${bloc}" ]] && {
			! [[ -d "${gbl_dir_ucg}/Unicode/${lg}" ]] && mkdir -p "${gbl_dir_ucg}/Unicode/${lg}";
			{ echo "<unicode>" ;
# ne sélectionner que les lignes relatives aux symboles (class=symb)
			wget -q -O /dev/stdout ${gbl_web_Unicode}/${page}/ | sed -rn "\|^[[:space:]]*<li class=\"symb\"|{s|^[[:space:]]*(.*<a href=\"/../([[:xdigit:]]{4})/\">).[^<]*(<.*)$|\1\2\3|;p}" ;
			echo "</unicode>"; }  1>"${gbl_dir_ucg}/Unicode/${lg}/${bloc}";
			}
		tab_unicode="$(cat "${gbl_dir_ucg}/Unicode/${lg}/${bloc}")";
# relire la page en anglais pour simplifier la recherche des diacritiques que porte chaque caractère
		[[ "${3}" = "en" ]] && anal_dia="${tab_unicode}" || {
				temp="${tab_unicode}";
				lire_web_Unicode "${bloc}" "${type_entit}" en;
				tab_unicode="${temp}";
				}			
	}
##############################################################
# construction de la liste des blocs Unicode à introduire dans l'alphabet
#############################################################
# calcul du nom de la page web Unicode qui contient le bloc
	function nom_page_unicode {
		local bloc_retirer="${1}"
		local bloc_inclure="${2}"
		local retrait=${3};
		local xml="${4}";
		local bloc_tlstr
		[[ -z "${xml}" ]] && {
			xml="$(tempfile --prefix="ucg_" --suffix=".xml")";
			sup_xml="${xml}" ; 
			{ echo "<ucg>";
				wget -q -O /dev/stdout ${gbl_web_Unicode}/${gbl_lg_tlstr}/ | sed -n -r "/data-begin/p";
				echo "</ucg>"; } 1>"${xml}";
			};
		case "${retrait}" in
			"true"| "TRUE"| "") bloc_tlstr="${bloc_retirer}";;
			"false" | "FALSE") [[ -n "${bloc_inclure}" ]] && bloc_tlstr="${bloc_inclure}" || bloc_tlstr="${bloc_retirer}";;
			esac;
		bloc_tlstr="$(sed -r "s/^[[:space:]]*([^[:space:]].*$)/\1/" <<< "${bloc_tlstr}")"
# le nom du fichier dans le répertoire du pays (fr) est le nom anglais du bloc, contenu dans le nœud data-key
		local bloc="$(es "${xml}" | xmlstarlet sel -t -m "//a[.='${bloc_tlstr}']" -v "./@data-key")"
		[[ -n "${sup_xml}" ]] && rm "${sup_xml}" ;
		echo "${bloc}";
	}
#################################################
# visualisation de la page de caractères
###############################################
	function alphabet_web {
		xdg-open "${gbl_web_Unicode}/${gbl_lg_tlstr}/blocks/$(nom_page_unicode "${@}")";
}
######################################################
# constitution de la liste des blocs inclus dans l'alphabet
######################################################$	
	function alphabet_inclus {
		local xml="${1}";
#		alphabet="${gbl_dir_eff}/ucg_alphabet";
		! [[ -e "${gbl_alphabet}" ]] && touch "${gbl_alphabet}";
		fic_liste_en="$(tempfile --prefix="ucg_" --suffix=".txt")";	
# établir la liste des blocs inclus dans l'alphabet, en anglais
		[[ -s "${gbl_alphabet}" ]] && {
			alpha="$(cat "${gbl_alphabet}" | sup_nul)";
			echo "${alpha}" 1> "${gbl_alphabet}";
			while grep -v -f "${fic_liste_en}" -m 1  "${gbl_alphabet}" | grep -o -E ":[^:]+:$" 1>>"${fic_liste_en}"; do : ; done;
			}
# le nom dans la langue de l'utilisateur se trouve dans le nœud "a" de la page html dont l'attribut data-key est le nom en anglais
		cat "${fic_liste_en}" | while read bloc; do
			[[ -z "${bloc}" ]] && break;
			bloc="$(tr -d ":" <<< "${bloc}")";
			es "${xml}" | xmlstarlet sel -t -m "//a[@data-key='${bloc}']" -o ":" -v "." -o ":" -n;
			done | sort ;
	}
###############################################################
# dialogue de constitution de l'alphabet
##############################################################	
	function alphabet_creer {
		local blocs_alphabet=;
		local blocs_inclure=;
		local fic_xml="$(tempfile --prefix="ucg_" --suffix=".xml")";
		local blocs_inclus="$(tempfile --prefix="ucg_" --suffix=".txt")";
		{ echo "<ucg>"; wget -q -O /dev/stdout ${gbl_web_Unicode}/${gbl_lg_tlstr}/ | sed -n -r "/data-begin/p"; echo "</ucg>"; } 1>/"${fic_xml}";
		alphabet_inclus "${fic_xml}" 1>"${blocs_inclus}"
# blocs_alphabet contient la liste des blocs inclus dans l'alphabet
		blocs_alphabet="$(cat "${blocs_inclus}" | tr -d ":" | tr "\n" ":" | sed -r "s/(.*):/\1/")";
# blocs_inclure contient la liste des blocs Unicode non présents dans l'alphabet et susceptibles d'y être inclus		
		blocs_inclure="$(xmlstarlet sel -t -m "//a" -o ":" -v "." -o ":" -n <"${fic_xml}" | sort | grep -v -f "${blocs_inclus}" | tr -d ":" | tr "\n" ":" | sed -r "s/(.*):/\1/")"
		yad --form --title="ucg : Gestion de l'alphabet" --button="gtk-ok:0"  --button=Annuler:1 \
			--width=900 --item-separator=":" --separator=":" \
			--always-print-result --sticky --center \
			--field="Blocs inclus dans l'alphabet (1):CB" \
			--field="Blocs non inclus dans l'alphabet (2):CB" \
			--field="Cocher pour retirer/visualiser le bloc inclus (1), ne pas cocher pour intégrer/visualiser le bloc non inclus (2):CHK" \
			--field="Visualiser le bloc (1) ou (2):BTN" \
			--field="Retirer/Intégrer à l'alphabet les caractères du bloc (1) ou (2):BTN" \
			"${blocs_alphabet}" \
			"${blocs_inclure}" \
			"FALSE" \
			"${gbl_script} alphabet_web %1 %2 %3 ${fic_xml}" \
			"@${gbl_script} alphabet_gerer %1 %2 %3 ${fic_xml} ${blocs_inclus}";
				}
##################################################################
# gestion du contenu de l'alphabet
################################################################
	function alphabet_gerer {
		local bloc_retirer="${1}"
		local bloc_inclure="${2}"
		local retrait=${3};
# si retrait=TRUE, alors il s'agit de retirer le bloc "${bloc_retirer}", sinon, il s'agit d'ajouter le bloc "${bloc_inclure}"
		local xml="${4}";
		local blocs_inclus="${5}";
######################################################
# retrait du bloc de l'alphabet
##################################################### 
		function alphabet_retrait {
			fic_liste_en="$(tempfile --prefix="ucg_" --suffix=".txt")";
			while grep -v -f "${fic_liste_en}" -m 1  "${gbl_alphabet}" | grep -o -E ":[^:]+:$" 1>>"${fic_liste_en}"; do : ; done;
			lb="$(cat "${fic_liste_en}")" 
			lb="$(echo "${lb}" | tr "\n" " ")";
			touch ${gbl_dir_ucg}/xtrace
			exec 2>> ${gbl_dir_ucg}/xtrace
			export BASH_XTRACEFD=2
			set -o xtrace
			echo "$(date)"
			echo "${lb}"
			x="$(grep -c -e "" "${gbl_alphabet}")";
			x="${x}"
			x="${bloc}";
			x="$(grep -c -e ":${bloc}:" "${gbl_alphabet}")";
			x="${x}"
			x="$(grep -c -v -e ":${bloc}:" "${gbl_alphabet}")";
			x="${x}"
			case "${gbl_cas_teste}" in
				var) 
					alpha="$(grep -v -e ":${bloc}:" "${gbl_alphabet}")";
					echo "${alpha}" 1>"${gbl_alphabet}" ;;
				grep)
					shopt -s lastpipe
					cat "${gbl_alphabet}" | grep -v -e ":${bloc}:" 1>"${gbl_alphabet}";;
				sed)
					cat "${gbl_alphabet}" | sed -r "/${bloc}.$/d" 1>"${gbl_alphabet}";;
				esac;
			x="$(grep -c -e "" "${gbl_alphabet}")";
			x="${x}"
			set +o xtrace			
		}
######################################################
# ajout du bloc dans l'alphabet
##################################################### 
		function alphabet_ajout {
			local fic_dia=$(tempfile -m 777 -p "ucg_" -s ".txt") ;
			notify-send -t 1000 "Alphabet ajout : ${bloc}" "Gestion de l'alphabet";
			lire_web_Unicode "${bloc}" blocks "${gbl_lg_tlstr}";
			while read def_car; do
				codeu="$(xmlstarlet sel -t -v "//li/a" <<< "${def_car}")" ;
				carg="$(eval "echo $'\\U${codeu}'")";
				titre="$(xmlstarlet fo -o -e utf-8 - <<< "${def_car}" | xmlstarlet sel -t -v "//li/@title" )"; 
				echo ":${carg}:U${codeu}:$(hxdp ${carg}):${ltr_xc}:${codeu}:${titre}:${bloc}:" 1>>"${gbl_alphabet}";
			done < <(echo "${tab_unicode}" | grep "^[[:space:]]*<li") ;
			rm "${fic_dia}";
		}		
		bloc="$(nom_page_unicode "${@}")";
		case "${retrait}" in
			"true" | "TRUE"| "") alphabet_retrait ;;
			"false" | "FALSE") alphabet_ajout ;;
			esac;
		alphabet_inclus "${xml}" 1>"${blocs_inclus}"
		blocs_alphabet="$(cat "${blocs_inclus}" | tr -d ":" | tr "\n" ":" | sed -r "s/(.*):/\1/")";
		blocs_inclure="$(xmlstarlet sel -t -m "//a" -o ":" -v "." -o ":" -n <"${xml}" | sort | grep -v -f "${blocs_inclus}" | tr -d ":" | tr "\n" ":" | sed -r "s/(.*):/\1/")"
		echo "1:${blocs_alphabet}"; echo "2:${blocs_inclure}";
	}
# suppression de l'expansion des noms de fichiers
	set -f
	init_gbl
	"${@}";

Arbiel

Dernière modification par Arbiel (Le 11/12/2017, à 23:16)


Arbiel Perlacremaz
LDLC Aurore NK3S-8-S4 Ubuntu 20.04
Abandon d'azerty au profit de bépo, de google au profit de Lilo et de la messagerie électronique violable au profit de Protonmail, une messagerie chiffrée de poste de travail à poste de travail.

Hors ligne

#7 Le 12/12/2017, à 09:02

pingouinux

Re : [cliquer ici pour explications] Ne pas tenter : fic>pipeline>fic

Je n'ai évidemment pas tout regardé en détail, mais ai réussi à reproduire le résultat aléatoire (et ce n'est pas une fois sur deux).

$ cat iarb0
:μ:U03BC:ce-bc:mu::Lettre minuscule grecque Mu:greek-coptic:
:ν:U03BD:ce-bd:nu::Lettre minuscule grecque Nu:greek-coptic:
:ξ:U03BE:ce-be:xi::Lettre minuscule grecque Xi:greek-coptic:

$ cp iarb0 iarb; cat iarb | grep -v mu >iarb; echo "iarb out"; cat iarb
iarb out
:ν:U03BD:ce-bd:nu::Lettre minuscule grecque Nu:greek-coptic:
:ξ:U03BE:ce-be:xi::Lettre minuscule grecque Xi:greek-coptic:

$ cp iarb0 iarb; cat iarb | grep -v mu >iarb; echo "iarb out"; cat iarb
iarb out

Ça confirme qu'il ne faut pas rediriger le résultat d'une série de commandes sur un fichier utilisé dans une de ces commandes. J'ignore pourquoi ça marche parfois. roll

Ajouté :
Par exemple, en exécutant la commande ci-dessus 1000 fois dans une boucle, le résultat a été correct 16 fois.

Dernière modification par pingouinux (Le 12/12/2017, à 09:17)

Hors ligne

#8 Le 12/12/2017, à 15:17

Arbiel

Re : [cliquer ici pour explications] Ne pas tenter : fic>pipeline>fic

Bonjour

il semble qu'en mode conversationnel la redirection de la sortie d'un pipeline sur le fichier lu en entrée fonctionne parfaitement, ce qui n'aide pas la recherche de la source d'une erreur constatée en bout de course. Je procédais généralement de la sorte, en recopiant dans le terminal les commandes du script en cours de mise au point. Je vais me réorienter vers une utilisation plus systématique de la trace, maintenant que je sais, grâce à toi, comment la rediriger vers un fichier.

Il est possible que l'erreur ne se produise que sous certaines conditions de traitement du ficher, ou du nombre de commandes exécutées le long du pipeline. Je vais essayer de prendre le temps de faire des tests sur la base de ce que tu as fait, et qui est beaucoup plus lisible que l'extrait de mon script et que la trace.

Sais-tu si, au sein de l'équipe ubuntu, quelqu'un est supposé centraliser les signalement d'erreurs, et intervenir, au nom de la collectivité sur launchpad ? Une telle intervention, d'une certaine manière officielle et proprement argumentée, aurait plus de chance d'être prise en considération qu'un rapport d'anomalie rédigé par un inconnu.

Arbiel


Arbiel Perlacremaz
LDLC Aurore NK3S-8-S4 Ubuntu 20.04
Abandon d'azerty au profit de bépo, de google au profit de Lilo et de la messagerie électronique violable au profit de Protonmail, une messagerie chiffrée de poste de travail à poste de travail.

Hors ligne

#9 Le 12/12/2017, à 15:43

pingouinux

Re : [cliquer ici pour explications] Ne pas tenter : fic>pipeline>fic

Je pense que le comportement normal est l'écrasement du fichier, et qu'il faut systématiquement passer par un fichier intermédiaire.

Hors ligne

#10 Le 12/12/2017, à 15:46

Arbiel

Re : [cliquer ici pour explications] Ne pas tenter : fic>pipeline>fic

Cela ne me paraît pas évident, compte tenu du fait que le pipeline fonctionne (semble fonctionner systématiquement) en mode interactif.


Arbiel Perlacremaz
LDLC Aurore NK3S-8-S4 Ubuntu 20.04
Abandon d'azerty au profit de bépo, de google au profit de Lilo et de la messagerie électronique violable au profit de Protonmail, une messagerie chiffrée de poste de travail à poste de travail.

Hors ligne

#11 Le 13/12/2017, à 00:18

Arbiel

Re : [cliquer ici pour explications] Ne pas tenter : fic>pipeline>fic

Bonsoir

tee en dernière commande du pipeline rétablit la situation, même si le fichier autre que la sortie standard sur lequel tee écrit est remplacé par /dev/null, comme le montre le test ci-dessous

#! /bin/bash
cd /tmp ;
function rd {
	while read ligne; do [[ -n "${ligne}" ]] && echo "${ligne}"; done;
}
i=0
j=0
	while [[ $((i++)) -lt $((${2})) ]]; do
		case "${1}" in
			tee)
				cat extrait 1>test2 ; cat test | tee test3 >test; md5sum test | sed -r "s/test/test2/" | md5sum -c --status || j=$(($j+1)) ;;
			cat)
				cat extrait 1>test2 ; cat extrait 1>test; cat test | cat >test; md5sum test | sed -r "s/test/test2/" | md5sum -c --status  || j=$(($j+1)) ;;
			cct)
				cat extrait 1>test2 ; cat extrait 1>test; cat test | cat | cat >test; md5sum test | sed -r "s/test/test2/" | md5sum -c --status  || j=$(($j+1)) ;;
			ccc)
				cat extrait 1>test2 ; cat extrait 1>test; cat test | cat | cat | cat >test; md5sum test | sed -r "s/test/test2/" | md5sum -c --status  || j=$(($j+1)) ;;
			cte)
				cat extrait 1>test2; cat test | cat | tee test3 >test; md5sum test | sed -r "s/test/test2/" | md5sum -c --status  || j=$(($j+1)) ;;
			tenul)
				cat extrait 1>test2 ; cat extrait 1>test ; cat test | tee /dev/null >test; md5sum test | sed -r "s/test/test2/" | md5sum -c --status || j=$(($j+1)) ;;
			grs)
				grep -e "U1F13" extrait 1>test2 ; cat extrait 1>test; cat test | grep -e "U1F13" >test; md5sum test | sed -r "s/test/test2/" | md5sum -c --status || j=$(($j+1)) ;;
			grc)
				grep -e "U1F13" extrait 1>test2 ; cat extrait 1>test; cat test | grep -e "U1F13" | cat >test; md5sum test | sed -r "s/test/test2/" | md5sum -c --status || j=$(($j+1)) ;;
			gre)
				grep -v -e "U1F13" extrait 1>test2 ; cat extrait 1>test; cat test | grep -v -e "U1F13" >test; md5sum test | sed -r "s/test/test2/" | md5sum -c --status || j=$(($j+1)) ;;
			tr)
				cat extrait | tr ":" ";" 1>test2 ; cat extrait 1>test; cat test | tr ":" ";" >test; md5sum test | sed -r "s/test/test2/" | md5sum -c --status || j=$(($j+1)) ;;
			rd)
				cat extrait 1>test2 ; cat extrait | rd 1>test; md5sum test | sed -r "s/test/test2/" | md5sum -c --status || j=$(($j+1)) ;;
			esac
		done;		
	echo "$1 = $j erreurs"
remi@remi-Vostro-3550:/tmp$ for f in tee cat cct ccc cte tenul grs gre grc tr rd; do bogue "${f}" 500; done;
tee = 499 erreurs
cat = 491 erreurs
cct = 462 erreurs
ccc = 476 erreurs
cte = 500 erreurs
tenul = 488 erreurs
grs = 487 erreurs
gre = 478 erreurs
grc = 468 erreurs
tr = 471 erreurs
rd = 0 erreurs
remi@remi-Vostro-3550:/tmp$ 

Seule la fonction rd que j'ai introduite et qui fait exactement ce que fait cat no provoque aucune erreur.

Arbiel

Dernière modification par Arbiel (Le 13/12/2017, à 00:43)


Arbiel Perlacremaz
LDLC Aurore NK3S-8-S4 Ubuntu 20.04
Abandon d'azerty au profit de bépo, de google au profit de Lilo et de la messagerie électronique violable au profit de Protonmail, une messagerie chiffrée de poste de travail à poste de travail.

Hors ligne

#12 Le 13/12/2017, à 10:47

Arbiel

Re : [cliquer ici pour explications] Ne pas tenter : fic>pipeline>fic

J'ai ouvert un rapport d'anomalie sur launchpad


Arbiel Perlacremaz
LDLC Aurore NK3S-8-S4 Ubuntu 20.04
Abandon d'azerty au profit de bépo, de google au profit de Lilo et de la messagerie électronique violable au profit de Protonmail, une messagerie chiffrée de poste de travail à poste de travail.

Hors ligne

#13 Le 13/12/2017, à 11:34

pingouinux

Re : [cliquer ici pour explications] Ne pas tenter : fic>pipeline>fic

Arbiel #11 a écrit :
			rd)
				cat extrait 1>test2 ; cat extrait | rd 1>test; md5sum test | sed -r "s/test/test2/" | md5sum -c --status || j=$(($j+1)) ;;

cat extrait | rd 1>test
C'est normal que tu n'aies pas d'erreur, car tu n'écris pas sur le fichier d'origine.
J'ai fait un test avec ta fonction, et j'obtiens 188 erreurs sur 1000.

$ for n in {1..1000}; do cp iarb0 iarb; cat iarb | rd >iarb; diff -q iarb0 iarb; done | grep -c differ
188

Hors ligne

#14 Le 13/12/2017, à 15:15

Arbiel

Re : [cliquer ici pour explications] Ne pas tenter : fic>pipeline>fic

Je te remercie de ta relecture attentive. Qu'il est difficile de se maintenir concentré, de se relire avec attention, et de réfléchir avant de conclure !!

Car je commence à voir d'où vient le problème. Les commandes du pipeline s'exécutent toutes dans leur propre sous-shell, ce qui veut dire qu'elles commencent à travailler avant que la précédente n'ait terminé sa tâche. Tu vois où je veux en venir : si la dernière commande ouvre en écriture le fichier que la première commande est encore en train de lire, il est évident que l'on court à la catastrophe.

Et le temps qui s'écoule entre le début de l'activité de la première commande et celui de la dernière commande nous est tout à fait inconnu, ce qui tend à nous laisser croire que le résultat est aléatoire.

Tu as travaillé sur un fichier de 3 lignes, alors que j'ai travaillé sur un fichier d'une bonne dizaine de lignes. Les résultats positifs que tu observes sont plus fréquents que les miens, ce qui paraît logique au vu de mon hypothèse.

J'avais remarqué, dans un script dans lequel la dernière commande du pipeline affichait dans un champ de dialogue les résultats de la commande précédente, qu'ils s'affichaient au fil de l'eau, ce qui semble là aussi confirmer mon hypothèse.

Je fais quelques tests, comme ne sélectionner que la dernière ligne du fichier, et je reviens dire ce qu'il en est.

Arbiel


Arbiel Perlacremaz
LDLC Aurore NK3S-8-S4 Ubuntu 20.04
Abandon d'azerty au profit de bépo, de google au profit de Lilo et de la messagerie électronique violable au profit de Protonmail, une messagerie chiffrée de poste de travail à poste de travail.

Hors ligne

#15 Le 13/12/2017, à 15:40

Arbiel

Re : [cliquer ici pour explications] Ne pas tenter : fic>pipeline>fic

#! /bin/bash
cd /tmp ;
i=0
j=0
	while [[ $((i++)) -lt $((${2})) ]]; do
		case "${1}" in
			der)
				cat /etc/fstab | sed -n -r "$p" 1>test2; cat /etc/fstab 1>test; cat test | sed -n -r "$p" >test; md5sum test | sed -r "s/test/test2/" | md5sum -c --status || j=$(($j+1)) ;;
			plus)
				cat /etc/fstab | sed -n -r "/#/p" 1>test2; cat /etc/fstab 1>test; cat test | sed -n -r "/#/p" >test; md5sum test | sed -r "s/test/test2/" | md5sum -c --status || j=$(($j+1)) ;;
			esac;
		done;		
	echo "$1 = $j erreurs"
remi@remi-Vostro-3550:/tmp$ for f in der plus; do bogue "${f}" 500; done;
der = 0 erreurs
plus = 479 erreurs
remi@remi-Vostro-3550:/tmp$ 

479 ce n'est pas beaucoup. Je pensais que ce serait 500 car la première et la dernière ligne de mon fichier sont des commentaires.

Arbiel

P.S
En lisant entre les lignes

Bash Reference Manual" a écrit :

3.2.3 Lists of Commands

A list is a sequence of one or more pipelines separated by one of the operators ‘;’, ‘&’, ‘&&’, or ‘||’, and optionally terminated by one of ‘;’, ‘&’, or a newline.

Of these list operators, ‘&&’ and ‘||’ have equal precedence, followed by ‘;’ and ‘&’, which have equal precedence.

A sequence of one or more newlines may appear in a list to delimit commands, equivalent to a semicolon.

If a command is terminated by the control operator ‘&’, the shell executes the command asynchronously in a subshell. This is known as executing the command in the background. The shell does not wait for the command to finish, and the return status is 0 (true). When job control is not active (see Job Control), the standard input for asynchronous commands, in the absence of any explicit redirections, is redirected from /dev/null.

Commands separated by a ‘;’ are executed sequentially; the shell waits for each command to terminate in turn. The return status is the exit status of the last command executed.

on peut effectivement comprendre que les commandes d'un pipeline ne sont pas exécutées séquentiellement.

Dernière modification par Arbiel (Le 13/12/2017, à 15:52)


Arbiel Perlacremaz
LDLC Aurore NK3S-8-S4 Ubuntu 20.04
Abandon d'azerty au profit de bépo, de google au profit de Lilo et de la messagerie électronique violable au profit de Protonmail, une messagerie chiffrée de poste de travail à poste de travail.

Hors ligne