IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Shell et commandes GNU Discussion :

[bash] printf ou l'art de justifier des caractères spéciaux


Sujet :

Shell et commandes GNU

  1. #1
    Futur Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2020
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2020
    Messages : 6
    Points : 6
    Points
    6
    Par défaut [bash] printf ou l'art de justifier des caractères spéciaux
    Bonjour à tous,

    Je me suis inscrit aujourd'hui au forum pour vous poser une question qui m'occupe depuis déjà quelques heures.
    Mon problème est simple : je veux pouvoir justifier du texte au milieu de mon terminal.
    Pour résoudre ce problème, j'ai rencontré la solution
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    printf '%*b\n' $(( ($COLUMNS+${#montexte})/2 )) "$montexte"
    dont je comprends la syntaxe.
    Tout se passe bien, mon 'ASCII art' pour commencer ma banner ssh (motd) se justifie correctement, mais alors survient le problème : dans une conditionnelle (if then), je veux afficher un message d'alerte si l'utilisateur est sudoer, et j'ai la bonne idée d'utiliser l'encodage ANSI (pour mes couleurs et effets, par exemple \e[0m).

    L'option b de printf me permet d'interpréter correctement la chaine (ie met en pratique les couleurs/effets), mais le problème est la longueur faussée de la chaine : des caractères invisibles (de style je suppose) sont comptés avec ${#montexte}.

    J'ai pu découvrir avec
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    echo -e $montexte | cat -v
    que '\e[0m' semble devenir '^[[0m', et j'ai donc essayé de supprimer ces caractères dans la chaine, au moins pour avoir la longueur (ensuite je les affichent pour avoir le style, hein) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    echo -e $montexte | sed -E 's:\^\[\[[0-9]+m::g'
    Bon ici tout vas bien, mais ce qui m'as fait craquer, c'est printf : la substition des caractères spéciaux semble différente. En effet, la longueur semblait totalement aléatoire pour arriver à un texte centré (sachant que printf attends la longueur de la chaine, qu'il complète au début par des espaces).

    J'ai vraiment besoin de votre aide, rien ne se trouve sur Internet à ma connaissance.
    Bonne journée à vous,
    Merci d'avance !

  2. #2
    Expert éminent sénior Avatar de disedorgue
    Homme Profil pro
    Ingénieur intégration
    Inscrit en
    Décembre 2012
    Messages
    4 266
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur intégration
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Décembre 2012
    Messages : 4 266
    Points : 12 681
    Points
    12 681
    Par défaut
    Bonjour et bienvenu,

    Je suis très étonné que ta substitution fonctionne car le '\e' qui se transforme en '^[' est juste un seul caractère dont la valeur octal est 033.

    Si tu veux obtenir le caractère sous sa forme '^[', il suffit de taper au clavier (azerty) :
    Ctrl-v puis Ctrl-AltGr-[

    sous sed, tu peux virer la sequence de control via sed -E 's/\o033\[[0-9]+m//g'.

    Mais le plus simple serais d'utiliser une variable pour tes controls et une variable pour ton texte, comme ça plus la peine de faire de la substitution
    Cordialement.

  3. #3
    Futur Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2020
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2020
    Messages : 6
    Points : 6
    Points
    6
    Par défaut Suite de l'aventure...
    Bien,

    Après des heures de rien du tout, me revoici de nouveau. J'ai beaucoup apprécié votre message, et le fait de savoir que "^[" n'est qu'un seul caractère m'a grandement aidé, par contre je tiens à ce que les paramètres soient incorporés dans le texte, pour faciliter l'usage (c'est une fonction en vérité).
    Pour orienter cette discussion dans la direction qui m'est problématique, voici donc mon problème reformulé :

    Dans le code suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    text=$1
    dumb=$(echo $text | grep -c "^[")
    plain=$(echo -e "$text" | sed -E 's/^[\[[0-9]+m//g')
    printf "%*b\n" $(( (($(tput cols)+${#plain})/2) + ${#text} - ${dumb} - ${#plain} )) "$text"
    qu'est-ce qui fait que mon texte n'est pas centré ?

    Ma démarche était la suivante:
    1) Comment je justifie un mot sans code ANSI ?
    => REPONSE : j'écris le mot à la fin d'une chaine de caractères de longeur {len(terminal) + len(mot)/2}.
    2) Quand j'ai des paramètres, je fais comment ?
    => REPONSE ? : je calcule la position comme si rien n'avait changé {len(plain)}, auquelle je rajoute tout le reste des caractères (avec une correction : dumb, car ^[ fait en vérité 2 caractères une fois affiché dans le terminal.

    Mais bon, ça se justifie pas exactement, et c'est encore plus flagrant dans du code comme celui-ci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    printf "%*b\n" $(( (($COLUMNS + 6) / 2) + 22 - 4 - 6)) "^[[0m^[[5m^[[6mHOURRA^[[0m"
    Un peu d'aide svp,
    Et merci d'avance !

  4. #4
    Modérateur
    Avatar de N_BaH
    Profil pro
    Inscrit en
    Février 2008
    Messages
    7 539
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 7 539
    Points : 19 361
    Points
    19 361
    Par défaut
    j'irais plus loin : séparer le format des données.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    chaine="HOURRAH"
    longRchaine=${#chaine}
    printf '\e[0;5m%*s\e[0m\n' $((($COLUMNS-$longRchaine)/2)) "$chaine"
    .
    N'oubliez pas de consulter les cours shell, la FAQ, et les pages man.

  5. #5
    Expert éminent sénior Avatar de Flodelarab
    Homme Profil pro
    Inscrit en
    Septembre 2005
    Messages
    5 238
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente (Poitou Charente)

    Informations forums :
    Inscription : Septembre 2005
    Messages : 5 238
    Points : 13 443
    Points
    13 443
    Par défaut
    Bonjour

    Tout d'abord, il est déconseillé de faire du texte justifié centré. C'est moche, inefficace, compliqué (tu confirmes ? ). En plus, si ton serveur ssh distant considère une console de 273 caractères de large et que ton client local fait 60 caractères de large, tu vas voir comme ça va être moche car décalé.

    La commande grep -c "^[" signifie "compte les lignes qui commencent par un crochet". Est-ce vraiment ce que tu voulais signifier ? Aucun rapport avec le \e ou \033 ou ^[ précédent ?
    Pour la commande sed -E 's/^[\[[0-9]+m//g'), rebelote. "^" signifie "début de ligne". Disedorgue t'as donné la bonne syntaxe.

    "code ANSI " .... Ah bon ? Tu n'es pas en utf-8 sous Linux ?

    Depuis le départ, tu nous parles de la couleur, mais pas de la tabulation. Pourtant c'est le plus gros problème que je vois. À l'affichage, elle se cale sur la position multiple de 8 la plus proche. Avec ton alignement centré, l'affichage devient aléatoire. Et la tabulation n'est toujours qu'un seul caractère.
    Sans interprétation, "toto\ttata" fait 10 caractères.
    Avec interprétation, "toto\ttata" fait 9 caractères.
    Mais, dans la réalité, ce n'est ni l'un, ni l'autre. 12 caractères.

    Je réalise bien que mon message n'est pas encourageant. Je présente mes excuses. Mais centrer est une sorte de FBI. (Fausse Bonne Idée).
    Cette réponse vous apporte quelque chose ? Cliquez sur en bas à droite du message.

  6. #6
    Futur Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2020
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2020
    Messages : 6
    Points : 6
    Points
    6
    Par défaut
    Merci tout d'abord pour vos réponses,

    En effet, je pense que je vais éviter finalement de me lancer dans tout ça, mais ça aura qd même été sympa de découvrir un peu sed.
    Mais j'aimerais qd meme un menu interactif avec l'utilisateur, un peu sympa, qui permettrai des raccourcis vers d'autres programmes shell.
    Je pensais utiliser des menus du type de ceux que par exemple on rencontre dans des installations de logiciel, comme l'installation d'un
    driver NVIDIA en ligne de commande.
    Ma principale préoccupation, c'est la sécurité de mon serveur, car je prévois d'en faire un serveur ftp...
    Des idées sur des pratiques courantes à mettre en place, et si un tel menu ne présente pas des failles/est {moche/inefficace/compliqué} ?

    En vérité, si vous trouvez certaines de mes pratiques un peu nazes, dites-le moi.

    PS: je mettrai en résolu qd j'aurai reçu éventuellement une réponse, sinon je ferme.

  7. #7
    Modérateur
    Avatar de N_BaH
    Profil pro
    Inscrit en
    Février 2008
    Messages
    7 539
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 7 539
    Points : 19 361
    Points
    19 361
    Par défaut
    adepte du KISS! je m'attends à lire les informations/questions sur la gauche de l'écran, à moins de fenêtres dialog, qui, par leur design, indiquent clairement où sont les informations/questions.
    .
    N'oubliez pas de consulter les cours shell, la FAQ, et les pages man.

  8. #8
    Expert éminent sénior Avatar de Flodelarab
    Homme Profil pro
    Inscrit en
    Septembre 2005
    Messages
    5 238
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente (Poitou Charente)

    Informations forums :
    Inscription : Septembre 2005
    Messages : 5 238
    Points : 13 443
    Points
    13 443
    Par défaut
    Ben justement. N'est-ce pas dialog qui prend en charge le centrage ?

    En tout cas, c'est le cas pour whiptail, zenity, yad.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    whiptail --inputbox "paquets" 10 25 "gimp inkscape ..."
    Cette réponse vous apporte quelque chose ? Cliquez sur en bas à droite du message.

  9. #9
    Modérateur
    Avatar de N_BaH
    Profil pro
    Inscrit en
    Février 2008
    Messages
    7 539
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 7 539
    Points : 19 361
    Points
    19 361
    Par défaut
    N'est-ce pas dialog qui prend en charge le centrage ?
    je ne comprends pas la question.
    c'est parce que j'ai avalé quelques mots ?
    à moins que des fenêtres dialog soient utilisées, car, par leur design, elles indiquent...
    .
    N'oubliez pas de consulter les cours shell, la FAQ, et les pages man.

  10. #10
    Expert confirmé
    Homme Profil pro
    Développeur informatique en retraite
    Inscrit en
    Avril 2008
    Messages
    2 101
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côtes d'Armor (Bretagne)

    Informations professionnelles :
    Activité : Développeur informatique en retraite

    Informations forums :
    Inscription : Avril 2008
    Messages : 2 101
    Points : 5 849
    Points
    5 849
    Par défaut
    Citation Envoyé par N_BaH Voir le message
    j'irais plus loin : séparer le format des données.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    chaine="HOURRAH"
    longRchaine=${#chaine}
    printf '\e[0;5m%*s\e[0m\n' $((($COLUMNS-$longRchaine)/2)) "$chaine"
    Je suis complètement d'accord avec N_BaH: séparer les données de la manière de les afficher!

    Si je regarde l'algorithme de ce que tu essaies de faire, avec ton usage de sed, ça ressemble à quelque chose comme:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    Soit la <donnée_brute> à afficher
    <jolie_donnée>      := formatage_en_couleurs(<donnée_brute>)
    <donnée_déformatée> := utiliser_sed_pour_déformater(<jolie_donnée>)
    <longueur_donnée>   := longueur(<donnée_déformatée>)
    affiche_donnée_formatée(<jolie_donnée>, <longueur_donnée>)
    Il me semble que ça illustre bien l'intérêt de ne pas mélanger la donnée brute de la donnée joliment formatée, non?

  11. #11
    Futur Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2020
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2020
    Messages : 6
    Points : 6
    Points
    6
    Par défaut La bonne voix ?
    Bonjour à tous,
    Je pense que Flodelarab a bien résumé les problèmes qui peuvent survenir avec de telles idées, et pour un serveur l'accessibilité à tous les utilisateurs est une priorité qui me semble primordiale. J'ai d'ailleurs un projet de terminal linux sur un écran de minitel, alors les petits écrans, je vais m'en coltiner...
    J'avais encore une fois songé à la séparation des données, mais je voulais vraiment rendre l'usage le plus facile possible. C'est sûr que pour la maintenance ça aurait déjà été plus facile de séparer, mais bon...
    Mais je vous remercie pour vos réponses, et super la référence "dialog", j'en apprends vraiment tous les jours ;D
    A+

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. bash => Perl : passer des caractères spéciaux
    Par kafifi dans le forum Langage
    Réponses: 8
    Dernier message: 27/01/2006, 23h20
  2. problème avec l'affichage des caractères spéciaux
    Par michelkey dans le forum Général Python
    Réponses: 4
    Dernier message: 19/08/2005, 09h09
  3. [XSLT] Remplacer par des caractères spéciaux
    Par OXyGN dans le forum XSL/XSLT/XPATH
    Réponses: 3
    Dernier message: 29/07/2005, 18h30
  4. traitement des caractères spéciaux avec XSLT
    Par Mirgue dans le forum XSL/XSLT/XPATH
    Réponses: 5
    Dernier message: 19/07/2004, 17h57
  5. Où trouver la liste des caractères spéciaux?
    Par gamez dans le forum Langage
    Réponses: 3
    Dernier message: 19/08/2003, 18h54

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo