8 votes

Retourner deux variables en awk

Pour le moment, voici ce que je fais

ret=$(ls -la | awk '{print $3 " "  $9}')
usr=$(echo $ret | awk '{print $1}')
fil=$(echo $ret | awk '{print $2}')

Le problème est que je n'exécute pas un ls Je lance une commande qui prend du temps, pour que vous puissiez comprendre la logique.

Existe-t-il un moyen de configurer la valeur de retour pour qu'elle définisse deux valeurs externes, comme par exemple

ls -la | awk -r usr=x -r fil=y '{x=$3; y=$9}'

De cette façon, la commande sera exécutée une fois et je peux la réduire à une seule ligne.

5voto

bob Points 380

Ce n'est pas très joli, mais si vous avez vraiment besoin de faire ça en une seule ligne, vous pouvez utiliser awk / bash Les capacités avancées de métaprogrammation de l'entreprise :)

eval $(ls -la | awk '{usr = $3 " " usr;fil = $9 " " fil} END{print "usr=\""usr"\";fil=\""fil"\""}')

Pour imprimer :

echo -e $usr
echo -e $fil

Personnellement, je m'en tiendrais à ce que vous avez - c'est beaucoup plus lisible et le surcoût de performance est minuscule comparé à ce qui précède :

$time <three line approach>

real    0m0.017s
user    0m0.006s
sys     0m0.011s

$time <one line approach>
real    0m0.009s
user    0m0.004s
sys     0m0.007s

4voto

olibre Points 6069

Une solution de contournement utilisant read

usr=""
fil=""
while read u f; do usr="$usr\n$u"; fil="$fil\n$f"; done < <(ls -la | awk '{print $3 " "  $9}')

Pour des questions de performance, vous pouvez utiliser <<< mais évitez-la si le texte renvoyé est volumineux :

while read u f; do usr="$usr\n$u"; fil="$fil\n$f"; done <<< $(ls -la | awk '{print $3 " "  $9}')

Un moyen plus portable inspiré de la réponse de @WilliamPursell :

$ usr=""
$ fil=""
$ while read u f; do usr="$usr\n$u"; fil="$fil\n$f"; done << EOF
> $(ls -la | awk '{print $3 " "  $9}')
> EOF

4voto

Perennial Points 155

Ce que vous voulez faire, c'est capturer la sortie de ls ou de toute autre commande et la traiter plus tard.

ls=$(ls -l)
first=$(echo $ls | awk '{print $1}')
second=$(echo $ls | awk '{print $2}')

2voto

olibre Points 6069

Utilisation de bash v4 tableau associatif :

unset      FILES
declare -A FILES
FILES=( ls -la | awk '{print $9 " "  $3}' )

Imprimer la liste du propriétaire et du dossier :

for fil in ${!FILES[@]}
do
  usr=${FILES["$fil"]}
  echo -e "$usr" "\t" "$fil"
done

Mes excuses, je ne peux pas tester sur mon ordinateur car mon bash La version 3.2 ne prend pas en charge tableau associatif :-(. Veuillez signaler tout problème...

2voto

William Pursell Points 56211

La réponse acceptée utilise la substitution de processus, qui est un bashisme qui ne fonctionne que sur certaines plateformes. Une solution plus portable est d'utiliser un heredoc :

read u f << EOF
$( ls ... )
EOF

Il est tentant d'essayer :

ls ... | read u f

mais la lecture s'exécute alors dans un sous-shell. Une technique courante est la suivante :

ls ... | { read u f; # use $u and $f here; }

mais pour rendre les variables disponibles dans le reste du script, le heredoc interpolé est l'approche la plus portable. Notez qu'elle nécessite que le shell lise toute la sortie du programme en mémoire, elle n'est donc pas adaptée si la sortie est censée être importante ou si le processus est long.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X