同じ行に2つの変数をエコーします。
2015-03-04.01.Abhi_Ram.txtを変数FILENAMEに保存し、変数COUNTに10を保存して、同時にエコーしたいです。
Sample.txt
2015-03-04.01.Abhi_Ram.txt 10
2015-03-04.02.Abhi_Ram.txt 70
以下は私が思いついたコードです:
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 |||| timestamp
db | Abhi_Ram | record_count | 10 |||| timestamp
db | Abhi_Ram | record_count | 2015-03-04.02.Abhi_Ram.txt |||| timestamp
db | Abhi_Ram | record_count | 70 |||| timestamp
誰かが私に欠けているものを私に指摘できますか?
考慮してください:
_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
_
これにより、ファイルが生成されます。
_$ 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
_
ノート:
シェル変数には小文字または大/小文字混合を使用するのがベストプラクティスです。システムは大文字の変数を使用するため、誤って変数を上書きすることは望ましくありません。
echo
ステートメント内の多くの二重引用符は不要でした。出力文字列全体を、1つの二重引用符で囲まれた文字列の中に含めることができます。
ファイルを一度に1行ずつ読み取りたい場合は、_while read ... done <inputfile
_構文を使用する方が安全です。 read
ステートメントにより、filename
およびcount
変数を簡単に定義することもできます。
コマンド置換の場合、多くの人がバックティック形式よりも$(...)
の形式を好みます。これは、(a)$(...)
によってコマンド置換の開始と終了が視覚的に区別されるため、(b)$(...)
フォームが適切にネストされ、(c)すべてのフォントが明確に表示されないためです通常のティックとは異なるバックティック。 (チェプナーに感謝します。)
効率化のため、_output.txt
_へのリダイレクトはループの最後に移動されました。このようにして、ファイルは一度だけ開かれ、閉じられます。 (Charles Duffyに感謝します。)
個々のエントリごとに_count_dt
_を更新する必要がない限り、ループの前に配置し、_sample.txt
_が処理されるたびに1回だけ設定できます。最新バージョンのbash(Mac OSXなし)がある場合は、_count_dt
_割り当てをネイティブのbashステートメントに置き換えることができます(ありがとう、Charles Duffy)(シェルアウトは不要です)。
_printf -v count_dt '%(%Y-%m-%d %H:%M:%S)T'
_
John1024はこれを正しく行う方法を説明しました。元のバージョンが機能しなかった理由を見てみたい。基本的な問題は、for
がループではなくwordsでループすることです。ファイルには各行に2つの単語(ファイル名とカウント)があるため、1行に2回ループを実行します。これを確認するには、次を試してください。
for line in `hadoop fs -cat sample.txt`
do
echo "$line"
done
...次のように出力されます:
2015-03-04.01.Abhi_Ram.txt
10
2015-03-04.02.Abhi_Ram.txt
70
...これはあなたが望んでいるものではありません。また、入力ファイルに「*」という単語が含まれている場合、現在のディレクトリにファイル名のリストを挿入するなど、他の不快な癖もあります。
while read ... done <file
アプローチは、シェルスクリプト内の行を反復処理する正しい方法です。たまたまawk
(この場合、read filename count
を使用する)を台無しにすることなく、各行をフィールドに分割することもできます。