Comment concaténer des chaînes formatées avec des printf dans bash
J'ai besoin de concaténer plusieurs chaînes en boucle et affecter le résultat à une variable:
Chaîne formatée exemple:
result=$(printf '| %-15s| %-25s| %-15s| %-15s| %-15s\n' $size $name $visits $inbound $outbound);
De mon point de vue, il doit travailler comme ceci:
result=''
while read somevar
do
...
outbound=`cat "$www_path/$name/access.log"|grep \`date +"%d/%b/%Y"\`|awk '{ sum+=$11} END {print sum/1024/1024}'`
result=$(printf '%s| %-15s| %-25s| %-15s| %-15s| %-15s\n' $result $size $name $visits $inbound $outbound);
...
done
echo $result
Mais il n'a pas 🙁
UPD:
Complet exemple de code ci-dessous:
www_path='/var/www';
result='';
cd /var/www/; ls -d */ | while read i ; do basename "$i" ; done
while read i;
do du -sh "$i"|
while read size name
do
visits=`cat "$www_path/$name/access.log"|grep \`date +"%d/%b/%Y"\`|grep -v "internal dummy connection"|awk -F ' ' '{print $1}' | sort | uniq | wc -l|tr '\n' '\t'|sed 's/$/\t/'`
inbound=`cat "$www_path/$name/access.log"|grep \`date +"%d/%b/%Y"\`|grep -v "internal dummy connection"|awk '{ sum+=$10} END {print sum/1024/1024}'|tr '\n' '\t'|sed 's/$/\t\t/'`
outbound=`cat "$www_path/$name/access.log"|grep \`date +"%d/%b/%Y"\`|grep -v "internal dummy connection"|awk '{ sum+=$11} END {print sum/1024/1024}'`;
result=$(printf '%s| %-15s| %-25s| %-15s| %-15s| %-15s\n' "$result" "$size" "$name" "$visits" "$inbound" "$outbound")
done
done
echo $result
Toujours assurez-vous que le code que vous postez une question reproduit le problème que vous rencontrez; l'original de votre post n'y est pas. La raison
Sur une autre note -- c'est incroyablement horrible code. Vous ne devriez jamais analyser la sortie de
result
est vide, c'est que vous attribuez à l'intérieur d'un shell interne est exécuté; ces modifications disparaissent après le shell interne est exécuté sorties. Il n'y avait aucun moyen pour nous de savoir ce basé sur l'original de votre question.Sur une autre note -- c'est incroyablement horrible code. Vous ne devriez jamais analyser la sortie de
ls
de cette façon; voir mywiki.wooledge.org/ParsingLs pour une explication de pourquoi, également, de faire le cat | grep
trois fois pour chaque ligne d'entrée est extrêmement inefficace.OriginalL'auteur user947668 | 2013-04-13
Vous devez vous connecter pour publier un commentaire.
D'utiliser des guillemets autour de $résultat et toutes les autres variables qui peuvent contenir d'espaces et autres caractères spéciaux s'ils doivent être utilisés comme un seul argument d'un programme ou d'une fonction intégrée:
Si vous voulez juste pour affecter le résultat de printf pour une variable (comme vous l'avez fait), vous pouvez également utiliser
BTW: il y a aussi un += opérateur d'affectation qui vient de ajoute aux chaînes (voir la page de manuel de bash, PARAMÈTRES de la section).
Dans le code complet d'inscription, un tuyau signe est manquant après le "fait" avant le second "tout lu i".
Et lorsque vous appelez
le contenu de $résultat est déjà perdu, depuis le printf est appelé dans un sous-processus créé par le tuyau de signer à la suite de " faire du ...'. Le parent processus n'ont pas accès à l' (environnement) les variables de la sous-processus.
Je préfère réécrire le code pour quelque chose comme
La
read < <(cmd)
expression est similaire àcmd | read
mais la première fait la commande dans le sous processus de la place, tandis que la lecture est exécutée dans le processus principal. De cette façon, les variables définies par la lecture peut être utilisé dans les commandes ultérieures.J'ai mis à jour la réponse, la chose principale est probablement l'accès à la suite env var de le premier processus parent
Jacob, je vous remercie. Votre code est beaucoup mieux!
Est-il POSIX manière la plus sûre pour remplacer Bash est
+=
opérateur? Voici mon code:ReplacementString=$(printf "%s" "\\x%d" "$ReplacementString" "CodePoint2")
(je suis en train d'analyser l'UCD) Sortie:U"\x%dCodePoint2",
OriginalL'auteur Jacob
Votre code à l'air bon. Une chose que vous avez besoin à faire, puisque
result
va contenir d'espaces que vous ajoutez à elle, est une citation de son expansion:En citant les autres variables, il peut ne pas être nécessaire, mais il est généralement une bonne idée.
Omettant de citer
$result
ne devrait pas provoquer d'être complètement vide, cependant. Vous pourriez avoir besoin de poster plus de code dans votrewhile
boucle.l'intégralité du code source a ajouté.
OriginalL'auteur chepner