Nouveau problème avec bash, besoin d'aide

Résolu/Fermé
gnugo - 27 févr. 2012 à 19:23
dubcek Messages postés 18718 Date d'inscription lundi 15 janvier 2007 Statut Contributeur Dernière intervention 22 mars 2024 - 28 févr. 2012 à 11:47
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

mamiemando Messages postés 33079 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 23 avril 2024 7 749
Modifié par mamiemando le 27/02/2012 à 20:19
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
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
mamiemando Messages postés 33079 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 23 avril 2024 7 749
28 févr. 2012 à 10:27
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
dubcek Messages postés 18718 Date d'inscription lundi 15 janvier 2007 Statut Contributeur Dernière intervention 22 mars 2024 5 615
28 févr. 2012 à 11:47
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