web-dev-qa-db-ja.com

awk:フィールドから文字列を抽出

入力フィールドはパイプ記号で区切られています:

CCCC|Sess C1|s1 DA=yy07:@##;/u/t/we
DDDDD|Sess C2|s4 DB=yy8:@##;/u/ba

最後のフィールドが変更された場所で出力を取得したい(このフィールドで最初の=と:の間にあるものだけが抽出される)

予想される出力は次のとおりです。

CCCC|Sess C1|yy07
DDDDD|Sess C2|yy8
2
Chris

標準のawkは、パターンに基づいてフィールドからデータを抽出することはあまり得意ではありません。いくつかのオプションが含まれます:

  • split()は、指定された区切り文字に基づいてテキストを配列に分割します。
  • match()は、RSTARTおよびRLENGTH変数を設定して、一致が発生した場所を示し、subtr()を使用して、一致した部分を抽出します。

だからここに:

_awk -F'|' -v OFS='|' '
  split($3, a, /[=:]/) >= 2 {print $1, $2, a[2]}' < file.txt
_

したがって、_=_の_:_または_$3_の最初と2番目の出現の間の部分を返します。

または:

_awk -F'|' -v OFS='|' '
  match($3, /=[^:]*/) {
    print $1, $2, substr($3, RSTART+1, RLENGTH-1)
  }' < file.txt
_

GNU awkには、sedsコマンドの機能をawkに組み込むgensub()拡張機能があります。

_gawk -F'|' -v OFS='|' '
  $3 ~ /=/ {
    print $1, $2, gensub(/^[^=]*=([^:]*).*/, "\\1", 1, $3)
  }' < file.txt
_

_=_に続いて任意の数の非_:_ sを検索し、_=_の後の部分を抽出します。 gensub()の問題は、置換が成功したかどうかを簡単に判別できないことです。そのため、最初に_$3_に_=_が含まれていることを確認してください。

sedの場合:

_sed -n 's/^\([^|]*|[^|]*|\)[^=|]*=\([^:|]*\).*/\1\2/p' < file.txt
_

Perlの場合:

_Perl -F'[|]' -lane 'print "$F[0]|$F[1]|$1" if $F[2] =~ /=([^:]*)/' < file.txt
_
6

やってみる

_awk -F\|  'BEGIN {OFS="|";} 
   {col=index($3,":"); 
    equ=index($3,"=");
    $3=substr($3,equ+1,col-equ-1); 
    print ; }' se
_

どこ

  • _-F\|_入力セパレータとして_|_を使用するようにawkに指示する
  • equ=index($3,"="); 3番目のフィールドの=のインデックスを取得
  • $3=substr($3,equ+1,col-equ-1);実際の置換を行います
4
Archemar

最初のサブはフィールド3の最初の6番目の文字を削除し、2番目のサブはコロンを含むすべてを削除します。

awk -F\| '{sub(/.{6}/,"",$3)sub(/:.*/,"")}1' OFS=\| file
0
Claes Wikner