web-dev-qa-db-fra.com

Écho de plusieurs variables dans la même ligne Bash

Je veux faire écho à deux variables sur la même ligne.
Je veux stocker 2015-03-04.01.Abhi_Ram.txt dans une variable FILENAME et 10 dans une variable COUNT et les afficher simultanément. 

Sample.txt 

2015-03-04.01.Abhi_Ram.txt 10
2015-03-04.02.Abhi_Ram.txt 70

Ci-dessous le code que j'ai créé: 

for line in `hadoop fs -cat sample.txt`
do

VAR="${line}"
FILENAME=`echo ${VAR}|awk '{print $1}'`
COUNT=`echo ${VAR}|awk '{print $2}'`
COUNT_DT=`date "+%Y-%m-%d %H:%M:%S"`
echo db"|"Abhi_Ram"|"record_count"|"${FILENAME}"||"${COUNT}"||"${COUNT_DT} >> output.txt
done

I want the output as:

db | Abhi_Ram | record_count | 2015-03-04.01.Abhi_Ram.txt || 10 || timestamp db | Abhi_Ram | record_count | 2015-03-04.02.Abhi_Ram.txt || 70 || timestamp

I'm getting the output as:

db | Abhi_Ram | record_count | 2015-03-04.01.Abhi_Ram.txt |||| horodatage
db | Abhi_Ram | record_count | 10 |||| horodatage
db | Abhi_Ram | record_count | 2015-03-04.02.Abhi_Ram.txt |||| horodatage
db | Abhi_Ram | record_count | 70 |||| horodatage 

Est-ce que quelqu'un pourrait me signaler ce qui me manque?

6
AS0207

Considérer:

while read filename count
do
    count_dt=$(date "+%Y-%m-%d %H:%M:%S")
    echo "db|Abhi_Ram|record_count|${filename}||${count}||${count_dt}"
done <sample.txt >>output.txt

Ceci produit le fichier:

$ cat output.txt 
db|Abhi_Ram|record_count|2015-03-04.01.Abhi_Ram.json||10||2015-08-10 14:42:39
db|Abhi_Ram|record_count|2015-03-04.02.Abhi_Ram.json||70||2015-08-10 14:42:39

Remarques:

  1. Il est recommandé d’utiliser une casse inférieure ou mixte pour vos variables Shell. Le système utilise des variables majuscules et vous ne voulez pas en écraser une par accident.

  2. Les nombreuses guillemets dans la déclaration echo étaient inutiles. La totalité de la chaîne de sortie peut être comprise dans une chaîne entre guillemets doubles.

  3. Si vous souhaitez lire un fichier ligne par ligne, il est préférable d’utiliser la construction while read ... done <inputfile. L'instruction read nous permet également de définir facilement les variables filename et count.

  4. Pour la substitution de commande, beaucoup préfèrent le formulaire $(...) au formulaire backtick. En effet, (a) la $(...) différencie visuellement le début et la fin de la substitution de commande, (b) la forme $(...) s'emboite bien et (c) toutes les polices ne montrent pas clairement les backticks différents des ticks classiques. (Merci Chepner.)

  5. Pour plus d'efficacité, la redirection vers output.txt a été déplacée à la fin de la boucle. De cette façon, le fichier n'est ouvert et fermé qu'une seule fois. (Merci Charles Duffy.)

  6. Sauf si vous avez besoin que count_dt soit mis à jour avec chaque entrée individuelle, il peut être placé avant la boucle et défini une seule fois à chaque fois que sample.txt a été traité. Si vous disposez d'une version à jour de bash (pas de Mac OSX), l'assignation count_dt peut être remplacée (merci Charles Duffy) par une instruction native bash (aucune suppression requise):

    printf -v count_dt '%(%Y-%m-%d %H:%M:%S)T'
    
9
John1024

John1024 a expliqué comment faire cela correctement; J'aimerais examiner pourquoi la version originale n'a pas fonctionné. Le problème fondamental est que for fait une boucle sur mots , pas sur des lignes. Le fichier a deux mots sur chaque ligne (un nom de fichier et un compte), de sorte qu'il exécute la boucle deux fois par ligne. Pour voir cela, essayez:

for line in `hadoop fs -cat sample.txt`
do
    echo "$line"
done

... et ça va imprimer quelque chose comme:

2015-03-04.01.Abhi_Ram.txt
10
2015-03-04.02.Abhi_Ram.txt
70

... ce que vous ne voulez pas du tout. Il a aussi quelques autres défauts désagréables, comme si le fichier d’entrée contenait le mot "*", il insérerait une liste de noms de fichiers dans le répertoire courant.

L'approche while read ... done <file est la bonne façon de parcourir des lignes dans un script Shell. Il se trouve que vous pouvez également fractionner chaque ligne en champs sans devoir manipuler awk (dans ce cas, read filename count le fait).

2
Gordon Davisson