Reputation: 23
I'm trying to get the exact field of the next record after a match, for example, if "string1" is matched in $2 then i need to get the value of $2 of next record. i have around 100 such strings to match each occurring exactly once in an input file. but the same search string can be present in a different input file (i have more than 1000 such input files).
sample input: comma separated
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....are search patterns contains alphanumeric with ({| in between. value fields can be empty. number of fields is not fixed. the location of string1 is not fixed. may occur in different position but will only occur once in a file.
what i tried so far:
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 know that this doesn't work for the given input since the i gets changed for consecutive value1 and value2. should i use different for loop for every single search string? or suggest any solution please.
for search
string1="AMR Range (QPSK) Slot02",string2="AMR Range (QPSK) {(Slot03)|(SW GRP2)}",string3="AMR Range (QPSK) Slot04",string4="AMR Range (16QAM) Slot02"
Desired output:
10.217.250.162,NTTN_EMS,Enable,Enable,,Enable
Upvotes: 0
Views: 283
Reputation: 204015
If you're ever considering using getline
be sure to first read and fully understand all the implications and caveats at http://awk.freeshell.org/AllAboutGetline
I don't understand how you get the posted expected output from the posted sample input but given this input:
$ 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)}
I think the following does what you describe in the text:
$ 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,
The above uses GNU awk for ENDFILE instead of END so you can do:
awk -f tst.awk strings file1 file2 ....
or similar to handle multiple files simultaneously.
If your strings have to be hard-coded in your awk script then it's just a tweak to:
$ 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,
Upvotes: 1
Reputation: 67507
I didn't understand your output format but perhaps this will help. This creates the mapping of search keywords to values in the corresponding next line
Changed your last input line
$ 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
and create a separate lookup file
$ cat lookup
string1
string2
string3
string4
string5
string6
and finally the script
$ 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
generates output
string1 value1
string2 value2
string3 value3
string4 value4
string5 value5
string6 value6
you can run the same script with multiple data files as well
$ awk ... lookup file1 file2 file3 ...
and perhaps add FILENAME in the print to identify which file was the source of the matches.
Upvotes: 1