Nouveau problème avec bash, besoin d'aide

Résolu
gnugo -  
dubcek Messages postés 18627 Date d'inscription   Statut Contributeur Dernière intervention   -
bonjour,
je rencontre encore une fois un problème avec bash : Je n'ai pas le même résultat en ligne de commande que dans un script

Pourriez vous m'expliquer pourquoi, et comment faire pour obtenir le même résultat avec mon script ?

Le but : établir une liste des doublons des arguments passés
Puis boucler sur chaque élément de cette liste pour faire diverses choses...

Sauf que quand mes éléments ont un espace, ça marche en ligne de commande mais pas en lançant le script
Voyez plutot :

$set "a a" "a a"
$liste="$(for f in "$@"; do echo $f; done)"
$echo "Liste = \"$liste\""
Liste = "a a
a a"
$
$doublons=$(sort<<<"$liste" | uniq -d)
$echo "Doublons = \"$doublons\""
Doublons = "a a"
$echo $doublons | od -c
0000000   a       a  \n
0000004
$for d in $doublons; do echo "$d X"; done
a a X
$
$
$cat pb
#!/bin/bash
liste="$(for f in "$@"; do echo $f; done)"
echo "Liste = \"$liste\""

doublons=$(sort<<<"$liste" | uniq -d)
echo "Doublons = \"$doublons\""
echo $doublons | od -c
for d in $doublons; do echo "$d X"; done
$
$./pb "a a" "a a"
Liste = "a a
a a"
Doublons = "a a"
0000000   a       a  \n
0000004
a X
a X
$


Ligne de cmd : j'ai bien un élément "a a"
Script : 2 éléments 'a'
Alors qu'on a fait la même chose. Non ?

4 réponses

  1. mamiemando Messages postés 33228 Date d'inscription   Statut Modérateur Dernière intervention   7 944
     
    Une manière de faire :

    #!/bin/sh  
    tmp=$(mktemp)
    (for x in "$@"; do echo $x; done) | sort | uniq -d > $tmp  
    
    while read ligne    
    do  
       # $ligne contient un argument en plusieurs exemplaires  
       echo $ligne  
    done < $tmp   
    
    rm -f $tmp


    ... qui donne :

    (mando@aldur) (~) $ sh toto.sh "a a" b "a a" c b d  
    a a  
    b


    Il y a peut-être moyen d'éviter de passer par un fichier temporaire avec une boucle while bien choisie mais je n'ai pas spécialement cherché ;-)

    Bonne chance
    1
  2. gnugo
     
    Salut, je te remercie ça marche bien comme ça!
    je fais donc un while read line sur mon "$doublons" au lieu d'un for et le problème est réglé.
    En plus c'est plus clair comme ça car on ne sait pas trop comment $doublons est transformé pour le for.

    Problème résolu.

    Mais si vous savez me dire pourquoi ma première solution ne fonctionne pas, ça m'interesse:-)

    En gros j'ai un
    doublons qui vaut :
    "a
    a b
    c d"

    Quand je fais un for sur $doublons ( et pas "$doublons" )
    en ligne de commande il traite bien a, puis "a b" puis "c d"
    mais lancé depuis un script, il traite a a b c d
    0
  3. mamiemando Messages postés 33228 Date d'inscription   Statut Modérateur Dernière intervention   7 944
     
    Parce que quand tu écris "for d in doublons", il itère sur la chaîne "a a" ce qui extrait non pas l'élément "a a" mais successivement "a", "a". Rajouter des guillemets autour de $doublons ne t'aidera pas plus car si par exemple tes doublons sont "a a" et "b b" il déclenchera une itération sur "a a b b" (la concaténation des doublons).

    C'est pour la même raison que je suis passée par un fichier intermédiaire dans le bout de code que je t'ai proposé.

    Bonne chance
    0
  4. dubcek Messages postés 18627 Date d'inscription   Statut Contributeur Dernière intervention   5 660
     
    hello
    $ ./f1 "a a" b "a a" c b d c
    a a
    b
    c
    $ cat f1
    #!/bin/bash
    
    printf "%s\n"  "$@" | sort | uniq -d |  while read ligne    
    do  
       # $ligne contient un argument en plusieurs exemplaires  
       echo $ligne  
    done 
    0