在awk

时间:2016-07-13 21:58:02

标签: awk gawk

我试图在匹配后获取下一条记录的确切字段,例如,如果" string1"匹配在$ 2然后我需要获得下一记录的$ 2的值。我有大约100个这样的字符串来匹配每个在输入文件中出现一次的字符串。但是相同的搜索字符串可以出现在不同的输入文件中(我有超过1000个这样的输入文件)。

示例输入:逗号分隔

10.217.250.162,NTTN_EMS,Radio / AMR Configuration Slot02,
RX RF Frequency Slot02,Channel Spacing Slot02,AMR Range (QPSK) Slot02,AMR Range (16QAM) Slot02
37740.500 [MHz],7 [MHz],Enable,Enable
10.217.250.162,NTTN_EMS,Radio / AMR Configuration Slot03,
RX RF Frequency (Slot03),Channel Spacing (Slot03),AMR Range (QPSK) {(Slot03)|(SW GRP2)},AMR Range (16QAM) {(Slot03)|(SW GRP2)}
37712.500 [MHz],7 [MHz],Enable,Enable
10.217.250.162,NTTN_EMS,Radio / AMR Configuration Slot04,
RX RF Frequency Slot04,Channel Spacing Slot04,AMR Range (QPSK) Slot04,AMR Range (16QAM) Slot04
,,,
10.217.250.162,NTTN_EMS,Radio / AMR Configuration Slot05,
RX RF Frequency (Slot05),Channel Spacing (Slot05),AMR Range (QPSK) {(Slot05)|(SW GRP3)},AMR Range (16QAM) {(Slot05)|(SW GRP3)}

string1,string2 ....是搜索模式包含字母数字与({|介于两者之间。 值字段可以为空。 字段数不固定。 string1的位置不固定。可能出现在不同的位置,但只会在文件中出现一次。

到目前为止我尝试了什么:

BEGIN {
FS=OFS=","
}
{for (i=1;i<=NF;i++){
if ($i == "string1"){
    getline val;
    split(val,a,",");
    am1=a[i]}
if ($i == "string2"){
    getline val;
    split(val,a,",");
    am2=a[i]}
}
}
END {print am1,am2}

我知道这对于给定的输入不起作用,因为i因连续的value1和value2而被更改。我应该为每个搜索字符串使用不同的for循环吗?或建议任何解决方案。

搜索

string1="AMR Range (QPSK) Slot02",string2="AMR Range (QPSK) {(Slot03)|(SW GRP2)}",string3="AMR Range (QPSK) Slot04",string4="AMR Range (16QAM) Slot02"

期望的输出:

10.217.250.162,NTTN_EMS,Enable,Enable,,Enable

2 个答案:

答案 0 :(得分:1)

我不了解你的输出格式,但也许这会有所帮助。这会创建搜索关键字到相应下一行中的值的映射

更改了您的上一个输入行

$ cat file
blah,blah,blah,string1,string2,string3,blah
blah,blah,blah,value1,value2,value3,blah
string4,blah,string5,string6,blah
value4,x,value5,value6,x

并创建一个单独的查找文件

$ cat lookup
string1
string2
string3
string4
string5
string6

最后是剧本

$ awk -F, 'NR==FNR{m[$0];next} 
            FNR==1{p=$0;next}
                  {n=split(p,a); 
                   for(i=1;i<=n;i++) if(a[i] in m) print a[i],$i; 
                   p=$0}' lookup file

生成输出

string1 value1
string2 value2
string3 value3
string4 value4
string5 value5
string6 value6

您也可以使用多个数据文件运行相同的脚本

$ awk ... lookup file1 file2 file3 ...

并且可能在打印中添加FILENAME以识别哪个文件是匹配的来源。

答案 1 :(得分:0)

我不明白你如何从发布的样本输入中获得已发布的预期输出,但是给出了这个输入:

$ cat strings
AMR Range (QPSK) Slot02
AMR Range (QPSK) {(Slot03)|(SW GRP2)}
AMR Range (QPSK) Slot04
AMR Range (16QAM) Slot02

$ cat file
10.217.250.162,NTTN_EMS,Radio / AMR Configuration Slot02,
RX RF Frequency Slot02,Channel Spacing Slot02,AMR Range (QPSK) Slot02,AMR Range (16QAM) Slot02
37740.500 [MHz],7 [MHz],Enable,Enable
10.217.250.162,NTTN_EMS,Radio / AMR Configuration Slot03,
RX RF Frequency (Slot03),Channel Spacing (Slot03),AMR Range (QPSK) {(Slot03)|(SW GRP2)},AMR Range (16QAM) {(Slot03)|(SW GRP2)}
37712.500 [MHz],7 [MHz],Enable,Enable
10.217.250.162,NTTN_EMS,Radio / AMR Configuration Slot04,
RX RF Frequency Slot04,Channel Spacing Slot04,AMR Range (QPSK) Slot04,AMR Range (16QAM) Slot04
,,,
10.217.250.162,NTTN_EMS,Radio / AMR Configuration Slot05,
RX RF Frequency (Slot05),Channel Spacing (Slot05),AMR Range (QPSK) {(Slot05)|(SW GRP3)},AMR Range (16QAM) {(Slot05)|(SW GRP3)}

我认为以下内容符合您在文中所描述的内容:

$ cat tst.awk
BEGIN { FS=OFS="," }
NR==FNR { strings[$0]; next }
FNR==1 { out = $1 OFS $2 }
{
    if (pos) {
        out = out OFS $pos
        pos = 0
    }
    for (i=1; i<=NF; i++) {
        if ($i in strings) {
            pos = i
        }
    }
}
ENDFILE {
    if (pos) {
        out = out OFS $pos
        pos = 0
    }
    print out
}

$ awk -f tst.awk strings file
10.217.250.162,NTTN_EMS,Enable,Enable,

上面使用GNU awk for ENDFILE而不是END,所以你可以这样做:

awk -f tst.awk strings file1 file2 ....

或类似的同时处理多个文件。

如果您的字符串必须在您的awk脚本中进行硬编码,那么它只是一个调整:

$ cat tst.awk
BEGIN {
    FS=OFS=","
    split("AMR Range (QPSK) Slot02\n\
AMR Range (QPSK) {(Slot03)|(SW GRP2)}\n\
AMR Range (QPSK) Slot04\n\
AMR Range (16QAM) Slot02", tmp, /\n/)
    for (i in tmp) {
        strings[tmp[i]]
    }
}
FNR==1 { out = $1 OFS $2 }
{
    if (pos) {
        out = out OFS $pos
        pos = 0
    }
    for (i=1; i<=NF; i++) {
        if ($i in strings) {
            pos = i
        }
    }
}
ENDFILE {
    if (pos) {
        out = out OFS $pos
        pos = 0
    }
    print out
}

$ awk -f tst.awk file
10.217.250.162,NTTN_EMS,Enable,Enable,