
テキストファイルから変数を抽出する簡単な方法はありますか?
たとえば、次のような出力がありますab
。
This is ApacheBench, Version 2.3 <$Revision: 1638069 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking bar (be patient)
Finished 1206 requests
Server Software: Jetty(9.0.z-SNAPSHOT)
Server Hostname: bar
Server Port: 5500
Document Path: /foo/1
Document Length: 148 bytes
Concurrency Level: 15
Time taken for tests: 30.041 seconds
Complete requests: 1206
Failed requests: 0
Total transferred: 359686 bytes
HTML transferred: 178636 bytes
Requests per second: 40.15 [#/sec] (mean)
Time per request: 373.643 [ms] (mean)
Time per request: 24.910 [ms] (mean, across all concurrent requests)
Transfer rate: 11.69 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 47 108 36.0 98 328
Processing: 73 264 782.5 150 7951
Waiting: 73 255 721.5 148 7886
Total: 129 371 783.5 259 8039
Percentage of the requests served within a certain time (ms)
50% 259
66% 293
75% 324
80% 340
90% 413
95% 525
98% 683
99% 6421
100% 8039 (longest request)
name: value
値(一致、以下の例を参照)を抽出し、1つのステップで変数に割り当てたいと思います。 (ab
一部のデータはcsvにエクスポートできますが、残りはフォーマットされたテキストでのみ使用できることを知っています。)
これまでに私が見つけた最高は次のとおりです。
path=$(cat text|grep 'Document Path:'|awk -F: '{ split($2, z, " "); print z[1]}')
total=$(cat text|grep 'Total transferred:'|awk -F: '{ split($2, z, " "); print z[1]}')
#[...]
しかし、これは少し繰り返されると思います。アッWard - 作業のためのより簡単な方法またはより良いツールはありますか?
答え1
私は通常、次のパターンを使用します。
. <(
awk 'BEGIN{print "shellvarname=\"value\""}'
)
awk
これは、シェル変数割り当て構文に使用できるステートメントを生成するために使用されます。この結果は(.
)からのものです。
特定の要件に応じて、次のオプションがあります。
. <(
awk -F': *' '
/Document Path/{printf "%s=\"%s\"\n", "path", $2}
/Total transferred/{printf "%s=\"%s\"\n", "total", $2}
' file
)
またはより短い
. <(
awk '
/Document Path/{printf "%s=\"%s\"\n", "path", $3}
/Total transferred/{printf "%s=\"%s\"\n", "total", $3}
' file
)
答え2
1-4単語を含むすべての行を見つけて、を使用して:
単語間のスペースを下線で置き換え、ペアvariable=value
で印刷します。その後、コンテンツ全体を転送してeval
設定できます。たとえば、
$ awk -F': *' '/^(\S+\s*){1,4}:/{gsub(/ /,"_",$1);print $1"=\""$2"\""}' file
Server_Software="Jetty(9.0.z-SNAPSHOT)"
Server_Hostname="bar"
Server_Port="5500"
Document_Path="/foo/1"
Document_Length="148 bytes"
Concurrency_Level="15"
Time_taken_for_tests="30.041 seconds"
Complete_requests="1206"
Failed_requests="0"
Total_transferred="359686 bytes"
HTML_transferred="178636 bytes"
Requests_per_second="40.15 [#/sec] (mean)"
Time_per_request="373.643 [ms] (mean)"
Time_per_request="24.910 [ms] (mean, across all concurrent requests)"
Transfer_rate="11.69 [Kbytes/sec] received"
Connect="47 108 36.0 98 328"
Processing="73 264 782.5 150 7951"
Waiting="73 255 721.5 148 7886"
Total="129 371 783.5 259 8039"
-F': *
フィールド区切り文字:
の後にゼロ個以上のスペースが続くように設定します。次に、スクリプトは、行が空白以外の文字(「単語」)が1〜4個発生し、その後に0個以上の空白が続く文字列と一致することを確認します:
。この行のため4を使用しています。
Time taken for tests: 30.041 seconds
次に、一致する行の最初のフィールドのすべてのスペースをアンダースコア(gsub(/ /,"_",$1)
)で置き換え、最初のフィールドanと引用符で囲まれ=
た2番目のフィールドを印刷します。文字列を印刷するには引用符で囲む必要があるため、引用符で囲まれたawk
文字列を印刷するには引用符$2
をエスケープする必要があります" \""
。
目的の出力が生成されたら、次のようにeval
変数を読み取ることができます。
$ eval $(awk -F': *' '/^(\S+\s*){1,4}:/{gsub(/ /,"_",$1);print $1"=\""$2"\""}' file)
$ echo $Transfer_rate
11.69 [Kbytes/sec] received
または直接インポートしてください。
. <(awk -F': *' '/^(\S+\s*){1,4}:/{gsub(/ /,"_",$1);print $1"=\""$2"\""}' file)
重要:危険です。eval
または、ファイルをインポートすると、ユーザーが提供したすべてのコードが実行されます。危険であることを確認しません。何らかの理由でスクリプトがawk
危険なものを返すと、幸せに実行されます。そのため、上記のコマンドを実行する前に出力結果を確認してください。受け入れられる答えも同じです。他のプログラムから返されたコードを盲目的に実行することは常に危険です。rm ~/*
eval
上記はGNUでは機能しますawk
が、より単純な実装では機能しませんawk
。システムで機能しない場合は、以下を試してください。
. <(awk -F': *' '/.*\s*: *:/{gsub(/ /,"_",$1);print $1"=\""$2"\""}' file)