ファイルの最後の行を[継続的に]読み取る方法は?

ファイルの最後の行を[継続的に]読み取る方法は?

クライアントがライブMQTTストリームからデータをフィルタリングし、ファイルにデータを書き込むようにしましたmyfile.csv。以下は最後の4行です。

1426134425,m,NWRL,MSV,001,d,SVlts,139,1840343,26089,28529,15987
1426134444,m,NWRL,MSV,001,d,status,139,1859000,23911,-33.836465,151.051189
1426134834,m,gf,TMX6BP,075,d,SVlts,216,1243746,27209,27409,17106
1426134845,m,gf,TMX6BP,075,d,status,216,1254000,179583,-33.836465,151.051189

この文書は常に更新されます。そのため、csvファイルの最後の行は引き続き変更されますが、フォーマットは変わりません。

尋ねる:myfile.csv7番目の値が "SVlts"の代わりに "status"のbashを使用してファイルの最後の行をどのように読み取ることができますか?この内容を読んだ後、4番目、5番目、10番目の値を3つの異なる変数にどのように割り当てますか?この値をプッシュしてMySQLテーブルを更新します。

したがって、出力は次のようになります。

variable_1=TMX6BP
variable_2=075
variable_3=179583

前述のように、これら3つの変数は、次の行が印刷されるまでMySQLテーブル(自己更新が必要です)を更新するためにプッシュ/転送されますmyfile.csv。そしてこれは繰り返し起こります。

答え1

これにより、最後の行で目的の情報がキャプチャされますfile

$ IFS=, read -r a b c var_1 var_2 d e f h var_3 extra < <(tail -n1 file)
$ echo $var_1  $var_2  $var_3
TMX6BP 075 179583

どのように動作しますか?

  • IFS=,

    これにより、フィールド区切り文字が一時的にコンマに設定されます。

  • read -r a b c var_1 var_2 d e f h var_3 extra

    これにより、フィールドがリストされた変数として読み込まれます。希望の名前を選択できます。

    上記では、最初のフィールドはシェル変数に割り当てられ、2番目のaフィールドはに割り当てられますb。それ以降に残ったものはすべてvar_3シェル変数に割り当てられますextra

  • < <(tail -n1 file)

    fileこれはコマンドの標準入力として最後の行を提供しますread。 1 つ目は、<リダイレクトに使用されるシェル記号です。この構成を<(...)プロセス置換と呼びます。最初と2番目の間隔は次<のとおりです。基本的な

答え2

短い答え:

   # tail -F: output appended data as the file grows
   #      Capital F to follow even if the file is reset to zero, recreated, etc.
   # awk -F, sets FS - Field Separator to a comma
   #   Inside awk: See if field 7 == "status" and print fields 4, 5 and 10
tail -F myfile.csv | awk -F, '$7 == "status" { print $4, $5, $10 }'

データベースの更新方法を書いていないので、始めるのに役立つものを書いてみましょう。

私が理解したところによれば、myfile.csvファイルを編集せずに、更新スクリプト/タスクへの入力と呼ばれる3つの変数を使用します。エラー確認などは皆様にお任せいたします。

まず、MySQL データベースを更新するスクリプトを作成します。ここではただ笑います。

#!/bin/bash
# update-MySQL-table.sh
    # redirecting stderr to stdout so awk will see it.
    # Not much use with "echo", but ...
echo $0 $1 $2 $3 2>&1

次に、CSVファイルを読み取り、解析し、データベース更新スクリプトを起動する別のスクリプトがあります。

#!/bin/bash
# parse-my-CSV-file.sh
csvfile="myfile.csv"

tail -n0 -F $csvfile | \
    awk -F, '
        $7 == "status" {
            cmd=sprintf("./update-MySQL-table.sh %s %s %s",$4,$5,$10)
            cmd | getline output
            print output
    }'

その後、解析スクリプトを起動したら、7番目のフィールドに「status」があるmyfile.csvに追加された新しい行がどのようにstdoutに印刷されるかを確認する必要があります。

答え3

私は次のことをします:

tail -n1 -f file | 
  perl -MDBI -F, -lane 'BEGIN{$d = DBI->connect(...)}
    if ($F[6] eq "status") {
      $d->do("INSERT INTO foo VALUES (?,?,?)", @F[3,4,9]);
    }'

関連情報