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 :

Mauvaise substitution en essayant de "compresser" deux lignes de commandes


Sujet :

Shell et commandes GNU

  1. #1
    Expert confirmé
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    11 208
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 11 208
    Par défaut Mauvaise substitution en essayant de "compresser" deux lignes de commandes
    Bonsoir,

    Si je fais
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
      ident="$(echo $liste | awk '{print $9}')"
      longueur_ident=${#ident}
    tout va bien, mais quoi que je tente pour tout avoir d'un seul coup, genre longueur_ident=${#"$(echo $liste | awk '{print $9}')"}, je me prends une "mauvaise substitution" : supprimer le $ avant le echo, supprimer les doubles quotes, rien n'est payant et je ne vois pas trop comment avancer…

    Une idée ?
    Merci,

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

    Informations forums :
    Inscription : Février 2008
    Messages : 7 723
    Par défaut
    oui. si quand tu insultes le shell en faisant n'importe quoi, tu te fais botter les fesses.
    normal.



    sans en savoir plus, difficile d'aller plus loin.

    bon, allez, au pire, a priori,
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    awk '{print length($9)}' <<<"$liste"
    ...
    ?

  3. #3
    Expert confirmé
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    11 208
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 11 208
    Par défaut
    Citation Envoyé par N_BaH Voir le message
    oui. si quand tu insultes le shell en faisant n'importe quoi, tu te fais botter les fesses.
    normal.
    Je le reconnais et l'accepte.

    Citation Envoyé par N_BaH Voir le message
    sans en savoir plus, difficile d'aller plus loin.
    Qu'est-ce que tu aurais voulu savoir de plus ?

    Citation Envoyé par N_BaH Voir le message
    bon, allez, au pire, a priori,
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    awk '{print length($9)}' <<<"$liste"
    ...
    ?
    Oui, ça fonctionne (pourquoi "au pire" ? C'est bien, ça), mais ça ne me satisfait qu'à moitié, j'aurais préféré une explication sur cette mauvaise substitution.
    Oui, je suis exigeant, mais comment apprendre, sinon ?
    Pourquoi passer par awk puisque bash est capable de renvoyer la longueur d'une string ?

    L'idée finale étant de trouver la chaîne la plus longue dans une liste de chaînes, je termine ainsi avec ta combine :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    [ $(awk '{print length($9)}' <<<"$liste") -gt $grande_longueur ] && grande_longueur=$longueur_ident

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

    Informations forums :
    Inscription : Février 2008
    Messages : 7 723
    Par défaut
    Qu'est-ce que tu aurais voulu savoir de plus ?
    pourquoi $liste est une simple variable, au lieu d'être un tableau ?
    d'où viennent les données qu'elle contient ? comment sont-elles "acquises" ?

  5. #5
    Expert confirmé Avatar de disedorgue
    Homme Profil pro
    Ingénieur intégration
    Inscrit en
    Décembre 2012
    Messages
    4 417
    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 417
    Par défaut
    Citation Envoyé par Jipété Voir le message
    Pourquoi passer par awk puisque bash est capable de renvoyer la longueur d'une string ?
    Non, bash est capable de te donner la taille d'un paramètre.

    Sinon, un exemple pure bash:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    $ yy=0
    $ xx="bob titi robert leonidas"
    $ yy=$( set $xx ; echo $(( ${#3} > yy  ? ${#3} : yy )) )
    $ echo $yy
    6
    $ yy=$( set $xx ; echo $(( ${#2} > yy  ? ${#2} : yy )) )
    $ echo $yy
    6
    En sachant qu'ici, il y a une raison de ne pas mettre entre guillemets $xx lors de set $xx.

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

    Informations forums :
    Inscription : Février 2008
    Messages : 7 723
    Par défaut trouver la chaîne la plus longue dans une liste de chaînes
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    $ liste="bob titi leonidas robert"
    $ for i in $liste; do test ${#i} -gt ${max:-0} && { max=${#i}; motlepluslong="$i";}; done
    $ echo "$motlepluslong"
    leonidas

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 5 300
    Par défaut
    Bonjour

    j'aurais préféré une explication sur cette mauvaise substitution.
    L'opérateur # a besoin d'un nom (de variable, ou de tableau). Or il n'y en a pas dans ta deuxième version. Tu as une substitution de commande. Donc il est perdu.

  8. #8
    Expert confirmé
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    11 208
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 11 208
    Par défaut
    Bonjour à tous,

    Citation Envoyé par N_BaH Voir le message
    pourquoi $liste est une simple variable, au lieu d'être un tableau ?
    Parce que je me suis rendu compte que ça fonctionnait comme je l'ai posté (c'était pour alléger le post)

    Citation Envoyé par N_BaH Voir le message
    d'où viennent les données qu'elle contient ? comment sont-elles "acquises" ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    while read liste
    do
    	ident="$(echo $liste | awk '{print $9}')"
    	disk="$(echo $liste | awk '{print $11}')"
    	disk=${disk:6}
    	printf "%-40s %s\n" $ident $disk
    done < <(ls -l /dev/disk/by-id | grep ata | grep -v sr)
    Et mon histoire de longueur c'est pour remplacer ce "40" un peu trop figé, et aligner proprement la sortie.

    Et donc grand merci pour tes trois lignes de code, c'est bien quelque chose comme ça que je cherchais.

    @disedorgue : strictement rien compris à ton exemple, désolé Nom : bah.gif
Affichages : 149
Taille : 275 octets

    Citation Envoyé par Flodelarab Voir le message
    L'opérateur # a besoin d'un nom (de variable, ou de tableau). Or il n'y en a pas dans ta deuxième version. Tu as une substitution de commande. Donc il est perdu.
    Tout s'explique ! Merci à toi,

    Allez hop !, et bon week-end prolongé.

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

    Informations forums :
    Inscription : Février 2008
    Messages : 7 723
    Par défaut
    Citation Envoyé par NBaH
    ON N'UTILISE PAS ls DANS UN SCRIPT !!!
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    $ Disks=() Targets=()
    $ for disk in /dev/disk/by-id/ata*; do id=${disk##*/}; target=$(readlink "$disk"); target=${target##*/}; Disks+=( "$id" ); Targets+=( "$target" ); test ${#id} -gt ${fmt:-0} && fmt=${#id};done
    $ for d in "${!Disks[@]}"; do printf "%${fmt}s %s\n" "${Disks[d]}" "${Targets[d]}"; done
          ata-WDC_WD10EADS-65L5B1_WD-WCAU4A103812 sda
    ata-WDC_WD10EADS-65L5B1_WD-WCAU4A103812-part1 sda1
    ata-WDC_WD10EADS-65L5B1_WD-WCAU4A103812-part2 sda2
    ata-WDC_WD10EADS-65L5B1_WD-WCAU4A103812-part3 sda3
    ata-WDC_WD10EADS-65L5B1_WD-WCAU4A103812-part4 sda4

  10. #10
    Expert confirmé
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    11 208
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 11 208
    Par défaut
    Citation Envoyé par N_BaH Voir le message
    Citation Envoyé par N_BaH
    ON N'UTILISE PAS ls DANS UN SCRIPT !!!
    Oui je sais, mais c'était présent dans le script dont je me suis inspiré, alors, pour faire vite, j'ai repris le truc.

    Sinon, je te remercie pour ton code, que j'ai testé à la va-vite par manque de temps, on y reviendra.

    Pour le moment, je voudrais conclure la v1 avec trois questions :
    d'abord le code sur lequel je m'appuie (avec ls, ):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    OLDIFS=$IFS
    IFS='\n' # nécessaire pour splitter les lignes
    i=0
    declare -a liste
    liste=$(ls -l /dev/disk/by-id | grep ata | grep -v sr)
     
    for elem in "${!liste[@]}"; do id=$(echo "$liste[elem]" | awk '{print $9}'); echo $id; [ ${#id} -gt ${max:-0} ] && { max=${#id}; echo "$max"; }; done 
    IFS=$OLDIFS
    et voilà sa sortie sur l'une de mes machines :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    ata-SAMSUNG_HD103SJ_S27EJ9BZ300246
    ata-SAMSUNG_HD103SJ_S27EJ9BZ300246-part1
    ata-SAMSUNG_HD103SJ_S27EJ9BZ300246-part2
    ata-SAMSUNG_HD103SJ_S27EJ9BZ300246-part3
    ata-SAMSUNG_HD103SJ_S27EJ9BZ300246-part4
    ata-ST31000528AS_9VPA4LYV
    ata-ST31000528AS_9VPA4LYV-part1
    ata-ST31000528AS_9VPA4LYV-part2
    288
    1-) d'où sort ce 288 ? J'ai bien un echo "$max" dans la boucle for, alors pourquoi juste une valeur ? Et même en écrivant ... && max=${#id}; echo "$max"; done j'obtiens un résultat identique.

    2-) d'où sort ce 288 ? Quand je compte à la main la longueur des 8 chaînes, j'ai 34+4x40+24+2x31=280. Est-ce que ce max incorpore le carriage-return de fin de ligne ?

    3-) d'où sort ce 288 qui semble représenter la somme des caractères des 8 chaînes alors que je m'attendais au nombre de caractères de la plus longue chaîne ?

    Merci pour les retours,

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

    Informations forums :
    Inscription : Février 2008
    Messages : 7 723
    Par défaut
    Citation Envoyé par N_BaH Voir le message
    Citation Envoyé par NBaH
    ON N'UTILISE PAS ls DANS UN SCRIPT !!!
    je vais donc faire ma mauvaise tête, et ne pas répondre. J'ai pas le temps : il faut que j'aille prendre mes calmants, ça urge, là.

    EDIT: ok, c'est plus fort que moi.

    liste n'est pas un tableau.
    le développement du tableau n'a donc pas lieu, et c'est la variable toute entière qui est traitée (dans un seul tour de la boucle for); soit 288 caractères.

  12. #12
    Expert confirmé
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    11 208
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 11 208
    Par défaut
    Salut salut,

    Citation Envoyé par N_BaH Voir le message
    je vais donc faire ma mauvaise tête, et ne pas répondre. J'ai pas le temps : il faut que j'aille prendre mes calmants, ça urge, là.

    Ça va mieux ce matin ?

    Citation Envoyé par N_BaH Voir le message
    EDIT: ok, c'est plus fort que moi



    Citation Envoyé par N_BaH Voir le message
    liste n'est pas un tableau.
    Ah ! Pourtant il me semble bien avoir mis, dans le code que j'ai donné, declare -a liste qui, d'après ce site (1re ligne du 1er §), déclare un… tableau !

    Citation Envoyé par N_BaH Voir le message
    […] et c'est la variable toute entière qui est traitée (dans un seul tour de la boucle for); soit 288 caractères.
    Et comment la variable toute entière peut-elle me sortir les huit lignes d'identification des disques que j'attends, toutes différentes, et pas huit fois la valeur de $max ?

  13. #13
    Expert confirmé
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    11 208
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 11 208
    Par défaut
    Citation Envoyé par Jipété Voir le message
    Sinon, je te remercie pour ton code, que j'ai testé à la va-vite par manque de temps, on y reviendra.
    Et donc voilà, comme dit Barbara,

    En un mot : excellent !

    J'ai juste remplacé printf "%${fmt}s par "%-${fmt}s pour avoir l'alignement à gauche, je trouve ça + agréable visuellement :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    ata-SAMSUNG_HD103SJ_S27EJ9BZ300246       sda
    ata-SAMSUNG_HD103SJ_S27EJ9BZ300246-part1 sda1
    ata-SAMSUNG_HD103SJ_S27EJ9BZ300246-part2 sda2
    ata-SAMSUNG_HD103SJ_S27EJ9BZ300246-part3 sda3
    ata-SAMSUNG_HD103SJ_S27EJ9BZ300246-part4 sda4
    ata-ST31000528AS_9VPA4LYV                sdb
    ata-ST31000528AS_9VPA4LYV-part1          sdb1
    ata-ST31000528AS_9VPA4LYV-part2          sdb2
    Par contre, j'aimerais bien une traduction en français courant de ${fmt:-0}, car je ne vois pas ce que ça veut dire. J'ai bien réussi à trouver, dans un micro-tuto sur les "variable substitutions", ${name:start}, mais j'ai du mal à comprendre ton start = -0… Le tuto me dit negative start counts from the end, ce qui ne m'avance guère car "counter" 0 sera toujours zéro, non ?, de quelque côté qu'on regarde.


    Et j'ai rajouté une ligne pour virer le lecteur de cd,
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    	...
    	target=${target##*/}       #; echo $target # sda
    	[ "$target" ==  "sr0" ] && continue
    	Disks+=( "$id" )
    	...
    mais je n'ai pas trouvé par quoi remplacer le "0" de "sr0" pour être plus générique. Une idée ?

    Merci pour les retours.

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 5 300
    Par défaut
    == n'existe pas, même dans les tests étendus, si je ne m'amuse.


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

    Informations forums :
    Inscription : Février 2008
    Messages : 7 723
    Par défaut
    la déclaration d'un tableau indexé est très facultative.
    il y a peut-être des cas où c'est obligatoire. Tout de suite, je n'en vois pas.
    dans une fonction, la déclaration d'un tableau réduit sa portée et le rend local à la fonction.
    pour construire un tableau simple, l'assignation doit se faire entre parenthèses.
    de plus, une substitution de commande sur plusieurs lignes dans une assignation de tableau ne donnera pas un tableau de plusieurs lignes, mais un tableau d'autant de mots qu'en affiche la commande.
    pour assigner le résultat d'une commande à un tableau, il faut utiliser mapfile, ou parcourir la sortie de la commande dans une boucle while.

    la "multi-linéalité" ( ) d'une variable dépend de sa mise entre guillemets :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    $ printf -v var '%s\n' foo bar baz
    $ echo "$var"
    foo
    bar
    baz
     
    $ echo $var
    foo bar baz
    ${variable:-valeur} : si la variable est vide, alors on utilise la valeur par défaut (valeur); cette valeur n'est pas pérenne.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    [[ $target == sr* ]] && continue
    entre crochets doubles, les guillemets sont facultatifs, et le double signe égal indique l'emploi de fonctionnalités que ne possèdent pas test et [.

    == existe bien en bash, mais n'est pas POSIX. test ne s'en plaint pas, mais, comme je l'ai dit précédemment, c'est un mauvais signal. Je préfère ne l'utiliser que dans les tests étendus ([[).

  16. #16
    Expert confirmé
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    11 208
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 11 208
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    #!/bin/bash
     
    variable="a"
    [ "$variable" == "a" ] && echo "ok" || echo "kc"
    [ "$variable" != "a" ] && echo "ok" || echo "kc"
    et voilà la sortie :
    Merci pour les crochets doubles et les autres explications, on a fait le tour, je crois.

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

Discussions similaires

  1. Compresser un fichier avec Winrar en ligne de commande
    Par da_latifa dans le forum Windows
    Réponses: 1
    Dernier message: 23/10/2010, 12h15
  2. Compression video en ligne de commande
    Par jaljal dans le forum Linux
    Réponses: 2
    Dernier message: 14/06/2010, 20h31
  3. [linux] Compression video en ligne de commande
    Par Sephiroth Lune dans le forum Vidéo
    Réponses: 1
    Dernier message: 11/09/2009, 17h44
  4. Compresser un fichier en ligne de commande
    Par silvaS dans le forum Shell et commandes GNU
    Réponses: 4
    Dernier message: 07/07/2006, 17h59

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