私は大容量ファイルからフォームデータを抽出しようとしました。非常に具体的なパターンが必要ですが、これまでは失敗しました。
ログの一貫した部分があります。
Machine info and user info blah blah blah [senderID=60,
ipaddress=/10.1.1.11:8443, serviceIdinList=[13], serviceBitbox=11111,
servicesList= | BeatController | BeatMaker | WaveShow, client=apache,
すべての行は次のように表示されます。
この行では、次のように作成する必要があります。
senderID=60, ipaddress=/10.1.1.11:8443, serviceIdinList=[13],
serviceBitbox=11111, servicesList= | BeatController | BeatMaker | WaveShow,
* "WaveShow"以降のすべての内容は、"senderID"以前のすべての内容と同様に関連していません。
私はここの投稿でこのコマンドを試しました。
sed -n '/servicesList=/{s/.*servicesList=//;s/\S*=.*//;p}'
しかし印刷のみです
servicesList= | BeatController | BeatMaker | WaveShow
grepとsedを使用して正規表現を使用していくつかの反復で修正しようとしましたが、進行しませんでした。
答え1
目的のジョブがと包含の間のすべてを出力する場合は、senderID=
次のWaveShow,
コマンドが必要ですsed
。
sed -n 's/.*\(senderID=.*WaveShow,\).*/\1/p'
これにより、\(
角かっこを使用して\)
これら2つの文字列間のすべての内容をキャプチャし\1
(\2
キャプチャがある場合など)を使用して出力します。
先行は.*
「貪欲」です。つまり、senderID=
文字列が入力に2回表示されると、最初の文字列が削除されます。これが望ましくない場合、sed
このツールはそれを処理できる正しいツールではありませんperl
。コマンドは次のとおりです。
perl -ne 'print if s/.*?(senderID=.*WaveShow,).*/$1/'
-n
「各入力行に対してループを実行し、ループの末尾に行を印刷しない」を意味します。-e
ループ内で実行する式を指定します。
?
変更後はできるだけ少なく一致してください(例:貪欲ではない一致).*
。*
括弧はPerlが部分をグループ化してキャプチャすることを可能にし、それから最初の$1
キャプチャ、$2
2番目のキャプチャなどとして使用できます。
しかし、これはPerlでこれを行う最善の方法ではありません。これは、不必要に文字列を変更したり、テキストをキャプチャしたり、印刷したりする作業を含まないので、はるかに優れています。
perl -ne 'print "$1\n" if /(senderID=.*WaveShow,)/'
Perlには、おそらくより効率的にこれを行うためのより多くの方法があります。
答え2
末尾のコンマが必要ですか?
それ以外の場合は、次のように動作します。
grep senderID filename | cut -d '[' -f 2- | cut -d ',' -f -5
出力:
senderID=60, ipaddress=/10.1.1.11:8443, serviceIdinList=[13], serviceBitbox=11111, servicesList= | BeatController | BeatMaker | WaveShow