行のフィールドをシェル変数として抽出する

行のフィールドをシェル変数として抽出する

以下のように何百もの行がありますconnRefused.log

        2015-12-12 00:12:10,227 ERROR [Testing-KeepAlive-01] c.v.v.v.Connection [Connection.java : 001] failed to bind to {name=TestGW,direction=BOTH_WAY,username=espada,password=whatever,binds=1,keepAliveInterval=60000,params={Payload=0, useEXP=1},thisOne={id=1001,name=TestGw,ip=192.168.0.1,port=88}}: Connection refused

connRefused.log以下は、配列を読み取るための私のスクリプト(簡体字)の一部です。

IFS=$'\n' read -d '' -r -a lines < /path/log/connRefused.log
for xx in "${lines[@]}"
  do
    ??? # what to do here?
    echo $Date
    echo $ID
    echo $Name
    echo $IP
    echo $Port
  done

上記の行から必要なデータを取得し、日付、ID、名前、IP、ポート変数に保存するにはどうすればよいですか?

thisOne={id=1001,name=TestGw,ip=192.168.0.1,port=88}

$Dateの場合、時間部分のみが必要です。

答え1

配列を使用する必要はありません。入力データが非常に規則的に見えるので、入力データをシェル割り当てステートメントに変換し、それをシェルに読み込んで計算します。このように:

#!/bin/sh

sed '
    s/^[-0-9]*  */date=/
    s/,.*thisOne={/ /
    s/}.*//
    s/,/ /g
' "$@" |
while read line
do
    eval $line
    echo date=$date
    echo id=$id
    echo name=$name
    echo ip=$ip
    echo port=$port
done

このsedコマンドは入力ラインを次に変換します。

date=00:12:10 id=1001 name=TestGw ip=192.168.0.1 port=88

ループwhileは一度に1行を読み取り、その行をシェルeval $lineで実行し、変数を与えられた値に設定します。

スクリプトはコマンドラインまたは標準入力からファイル名を処理します(コマンドの"$@"末尾に.があることに注意してくださいsed)。

このコマンドは、sed一連の(代替)コマンドを介してs行をシェル割り当てステートメントに変換します。

  1. 行の先頭()でのみダッシュと数字()の後に1つ以上のスペース()が続く^順序を次に置き換えます。[-0-9]**date=

    s/^[-0-9]*  */date=/
    
  2. カンマ.*の後にランダムな文字()とスペースが続く場合は置き換えます。thisOne=

    s/,.*thisOne={/ /
    
  3. 閉じる中括弧()を削除し、行の(暗黙的な)末尾に}他の文字()を削除します。.*

    s/}.*//
    
  4. すべてのカンマ(,)を空白に置き換えます。

    s/,/ /g
    

|サンプルスクリプトでは、ファイルの末尾にあるパイプを一時的に削除し、スクリプトのコマンドsed部分のみを実行してどのように機能するかを試すことをお勧めします。

関連情報