从数据块中获取键名/值对

从数据块中获取键名/值对

问题:需要以 340039 等开头的所有 IMSI 的列表,这些 IMSI 具有 EPS_PROFILE_ID、MMEFEATURELIST 的组合

输入

<BEGINFILE>
<SUBBEGIN
    IMSI=340039XXXXXXXXX;
    MSISDN=59995171393;
    EPS_PROFILE_ID=1;
    PLMNTPLID=1;
    SUB_DYN_EPS_ID=1;
    MMEHOST=XXXXXXXXXXXXXXXXXXXXXXXXXX.VVV.VV;
    MMEREALM=dwcxd.dnhjxcdws.cdnjkcd;
    EPS_IMEI=155186158551851658;
    EPS_IMEISV=01;
    MMEFEATURELIST=ALL_APN;
    MMETIMESTAMP=15513535;
    S4SGSNTIMESTAMP=0;
    HLR_INDEX=1;
    LTEAUTOPROV=NO;
    MPS=NO;
    RELAY=NO;
<SUBEND
<SUBBEGIN
IMSI=340038XXXXXXXXX;
    MSISDN=59995171393;
    PLMNTPLID=1;
    CURRENTNAM=BOTH;
    CAT=COMMON;
    TBS=TS11&TS12&TS21&TS22&TS61&BS26&BS2G;
    VLRLIST=2;
    SGSNLIST=2;
<SUBEND
<ENDFILE>

所需输出

IMSI=340039XXXXXXXXX;EPS_PROFILE_ID=1;MMEFEATURELIST=ALL_APN;

答案1

我更喜欢用于perl这种解析

perl -ne '
    $/ = "\n<SUBBEGIN\n";                     # Read blocks starting with this pattern
    ($i) = /\b(IMSI=340039[^;]*)/;            # Get IMSI and value
    ($e) = /\b(EPS_PROFILE_ID=[^;]+)/;        # Get EPS_PROFILE_ID and value
    ($m) = /\b(MMEFEATURELIST=[^;]+)/;        # Get MMEFEATURELIST and value
    print "$i;$e;$m;\n" if $i && $e && $m;    # Print result only if all three items are present
' input_file

您的示例的输出

IMSI=340039XXXXXXXXX;EPS_PROFILE_ID=1;MMEFEATURELIST=ALL_APN;

答案2

使用任何 POSIX awk:

$ cat tst.awk
BEGIN { FS="[[:space:]=]*"; OFS=";" }
/=/ { tag2val[$2] = $3 }
/<SUBEND/ {
    if ( (tag2val["IMSI"] ~ /^340039/) &&
         ("EPS_PROFILE_ID" in tag2val) &&
         ("MMEFEATURELIST" in tag2val) ) {
        print p("IMSI"), p("EPS_PROFILE_ID"), p("MMEFEATURELIST")
    }
    delete tag2val
}
function p(tag) { return tag "=" tag2val[tag] }

$ awk -f tst.awk file
IMSI=340039XXXXXXXXX;;EPS_PROFILE_ID=1;;MMEFEATURELIST=ALL_APN;

答案3

GNU sed这是使用扩展正则表达式模式(-E)解决问题的一种方法。

## holds the keys to be printed
var='IMSI EPS_PROFILE_ID MMEFEATURELIST'

sed -En '
  1{:1;x;s/.*/ '"$var"' /;x;}
  /^<SUBBEGIN$/,/^<SUBEND$/G
  /^\s+((\S+)=\S+)\n(.*) \2(\s)/!d
  s//\3\n\1\4/
  /(.*\n){3}/!{h;d;}
  /^\nIMSI=340039/s/\n|\s$//gp
  s/.*/<SUBEND/;b1
' file

IMSI=340039XXXXXXXXX;EPS_PROFILE_ID=1;MMEFEATURELIST=ALL_APN;

使用前瞻我们在正则表达式中与断言。

perl -lne '
  push(@A, $_)
    if my $e = /^<SUBBEGIN$/ ... /^<SUBEND$/;
  print($1, $2, $3)
    if $e =~ /E0/ && join($/, splice(@A)) =~
    m/(?:
        (?=$p(IMSI=340039$q))
        (?=$p(EPS_PROFILE_ID=$q))
        (?=$p(MMEFEATURELIST=$q))
    )/xms;

BEGIN {
  $q = qr/ (?:(?!;)\S)+; /xms;
  $p = qr/ \A.*\n\h* /xms;
}' file

## keys provided as env to awk
s="IMSI EPS_PROFILE_ID MMEFEATURELIST" \
awk -F '^[[:blank:]]+|=' '
BEGIN {
  n = split(ENVIRON["s"],a," ")
  for (var in a) b[a[var]] = var
}
/^<SUBBEGIN$/,/^<SUBEND$/ {
  if ( /=/ && $2 in b) {
    h[$2] = $0
    sub(FS, "", h[$2])
  }
  if ( /^<SUBEND$/ ) {
    t=$0;$0=""
    for (i=1; a[i] in h; i++) $i = h[a[i]]
    split("", h, "=")
    f = (NF == n) && ($1 ~ /=340039/)
  }
}
f;{f=0}
' OFS= file

答案4


awk '/IMSI=340039/&&/EPS_PROFILE_ID/&&/MMEFEATURELIST/' filename


相关内容