awk:从字段中提取字符串

Chr*_*ris 5 awk shell-script gawk

在输入字段中由管道符号分隔:

CCCC|Sess C1|s1 DA=yy07:@##;/u/t/we
DDDDD|Sess C2|s4 DB=yy8:@##;/u/ba
Run Code Online (Sandbox Code Playgroud)

我想获得最后一个字段更改的输出(仅提取第一个 = 和 : 在此字段中的内容

预期输出为:

CCCC|Sess C1|yy07
DDDDD|Sess C2|yy8
Run Code Online (Sandbox Code Playgroud)

Sté*_*las 8

标准awk不太擅长基于模式从字段中提取数据。一些选项包括:

  • split() 根据指定的分隔符将文本拆分为数组。
  • match()它设置RSTARTRLENGTH变量以指示匹配发生的位置,然后用于subtr()提取匹配的部分。

所以在这里:

awk -F'|' -v OFS='|' '
  split($3, a, /[=:]/) >= 2 {print $1, $2, a[2]}' < file.txt
Run Code Online (Sandbox Code Playgroud)

因此返回 a=:in第一次和第二次出现之间的部分$3

或者:

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

GNUawk有一个gensub()扩展,它将sed'ss命令的功能引入awk

gawk -F'|' -v OFS='|' '
  $3 ~ /=/ {
    print $1, $2, gensub(/^[^=]*=([^:]*).*/, "\\1", 1, $3)
  }' < file.txt
Run Code Online (Sandbox Code Playgroud)

查找=后跟任意数量的非:s 并提取 之后的部分=。问题gensub()在于您无法轻易判断替换是否成功,因此检查首先$3包含=

sed

sed -n 's/^\([^|]*|[^|]*|\)[^=|]*=\([^:|]*\).*/\1\2/p' < file.txt
Run Code Online (Sandbox Code Playgroud)

perl

perl -F'[|]' -lane 'print "$F[0]|$F[1]|$1" if $F[2] =~ /=([^:]*)/' < file.txt
Run Code Online (Sandbox Code Playgroud)


Arc*_*mar 4

我会尝试

awk -F\|  'BEGIN {OFS="|";} 
   {col=index($3,":"); 
    equ=index($3,"=");
    $3=substr($3,equ+1,col-equ-1); 
    print ; }' se
Run Code Online (Sandbox Code Playgroud)

在哪里

  • -F\|告诉 awk 用作|输入分隔符
  • equ=index($3,"=");获取第三个字段中 = 的索引
  • $3=substr($3,equ+1,col-equ-1); 进行实际替换