web-dev-qa-db-fra.com

résultats de wc en tant que variables

Je voudrais utiliser les lignes provenant de "wc" comme variables. Par exemple:

echo 'foo bar' > file.txt
echo 'blah blah blah' >> file.txt
wc file.txt

2  5 23 file.txt

J'aimerais associer quelque chose comme $lines, $words et $characters aux valeurs 2, 5 et 23. Comment puis-je faire cela en bash?

21
719016

Il existe d’autres solutions, mais une solution simple que j’utilise habituellement consiste à placer la sortie de wc dans un fichier temporaire, puis à lire à partir de là:

wc file.txt > xxx
read lines words characters filename < xxx 
echo "lines=$lines words=$words characters=$characters filename=$filename"
lines=2 words=5 characters=23 filename=file.txt

L'avantage de cette méthode est qu'il n'est pas nécessaire de créer plusieurs processus awk, un pour chaque variable. L'inconvénient est que vous avez besoin d'un fichier temporaire, que vous devez supprimer par la suite.

Attention, cela ne fonctionne pas:

wc file.txt | read lines words characters filename

Le problème est que la canalisation vers read crée un autre processus et que les variables y sont mises à jour, elles ne sont donc pas accessibles dans le shell appelant.

Edit: ajout de solution par arnaud576875:

read lines words chars filename <<< $(wc x)

Fonctionne sans écrire dans un fichier (et n’a pas de problème de pipe). C'est bash spécifique.

De la bash manuel:

Here Strings

   A variant of here documents, the format is:

          <<<Word

   The Word is expanded and supplied to the command on its standard input.

La clé est le bit "Word is expand".

10
dangonfast

En pure bash: (pas de awk)

a=($(wc file.txt))
lines=${a[0]}
words=${a[1]}
chars=${a[2]}

Cela fonctionne en utilisant les tableaux de bash. a=(1 2 3) crée un tableau avec les éléments 1, 2 et 3. Nous pouvons ensuite accéder à des éléments séparés avec la syntaxe ${a[indice]}.

Alternative: (à base de solution gonvalée)

read lines words chars <<< $(wc x)

Ou en sh:

a=$(wc file.txt)
lines=$(echo $a|cut -d' ' -f1)
words=$(echo $a|cut -d' ' -f2)
chars=$(echo $a|cut -d' ' -f3)
35
Arnaud Le Blanc

Juste pour ajouter une autre variante -

set -- `wc file.txt`
chars=$1
words=$2
lines=$3

Ceci évidemment clobbers $* et les variables associées. Contrairement à certaines des autres solutions proposées ici, il est portable sur d’autres coques Bourne. 

4
tripleee
lines=`wc file.txt | awk '{print $1}'`
words=`wc file.txt | awk '{print $2}'`
...

vous pouvez également stocker le résultat wc quelque part en premier .. et le parser ensuite .. si vous êtes pointilleux en matière de performance :)

3
duedl0r

Je voulais stocker le nombre de fichiers csv dans une variable. Ce qui suit a fonctionné pour moi:

CSV_COUNT=$(ls ./pathToSubdirectory | grep ".csv" | wc -l | xargs)
  • xargs supprime les espaces de la commande wc
  • J'ai couru ce script bash pas dans le même dossier que les fichiers csv. Ainsi, le chemin pathToSubdirectory
2
Simon Bachmann

Vous pouvez affecter une sortie à une variable en ouvrant un sous-shell:

$ x=$(wc some-file)
$ echo $x
1 6 60 some-file

Maintenant, afin d’obtenir les variables séparées, l’option la plus simple est d’utiliser awk:

$ x=$(wc some-file | awk '{print $1}')
$ echo $x
1
0
Konrad Rudolph
declare -a result
result=( $(wc < file.txt) )
lines=${result[0]}
words=${result[1]}
characters=${result[2]}
echo "Lines: $lines, Words: $words, Characters: $characters"
0
Adrian Pronk