4

appreciate any help with this task:

File A has 4 fields and has 90K lines. The first field (column 1) has a value that needs to be changed if criteria below met. The fourth field (column 4) has the data referenced in File B. The data in File A are tab separated DNS records:

Owner IN Type RData

FileA:

hostname1 IN A 10.10.20.1 
hostname2 IN A 10.10.20.2 
hostname3 IN A 10.10.20.3

FileB:

10.10.20.1 
10.10.20.2 
10.10.20.58 
10.10.21.245 
10.10.23.7

File B is single column (one field) and 1400 lines. The data in File B are IP addresses.

Requirement: For every line in File B, replace the contents of the the first field in File A if the fourth field in File A matches.

In English: For every IP that's listed in File B, replace the Owner value in File A with a specific value.

  • I want to answer your question, but can you add some samples of both files please? – Eng7 Aug 13 '15 at 5:05
  • File A: hostname1 IN A 10.10.20.1 hostname2 IN A 10.10.20.2 alias2 IN CNAME hostname2 hostname3 IN A 10.10.20.3 ... File B: 10.10.20.1 10.10.20.2 10.10.20.58 10.10.21.245 10.10.23.7 – Gordon Aug 13 '15 at 5:16
  • what is the value of field1 from fileA will be? – Eng7 Aug 13 '15 at 5:24
  • I need to change hostname to reserved. – Gordon Aug 13 '15 at 5:26
  • what can you program in? Perl? Python? Ruby? – Skaperen Aug 13 '15 at 11:43
3

(modifying from my answer here...)

You can compare NR with FNR to distinguish between processing the first or the subsequent files. This is because FNR is reset per file, while NR is the running tally. Therefore, only during the processing of the first file will the condition NR==FNR be satisfied.

To process FileB first...

awk 'NR==FNR{a[$1]=1}'

Setting the value to a 'dummy' one like 1 is good enough.

Then, to process FileA...

awk -F'\t' 'BEGIN{OFS=FS}NR!=FNR{if(a[$4]){$1="Reserved"};print}'

Here, the output field separator OFS is set as FS to preserve the formatting when awk reconstructs the full line ($0).

Putting both together:

awk -F'\t' 'BEGIN{OFS=FS}NR==FNR{a[$1]=1}NR!=FNR{if(a[$4]){$1="Reserved"};print}' FileB FileA

If you want it to be slightly more terse...

awk -F'\t' 'BEGIN{OFS=FS}NR==FNR{a[$1]=1;next}a[$4]{$1="Reserved"}1' FileB FileA

next is used in the processing of the first file to skip the final printing indicated by (the final) 1, which is a shortcut of doing {print $0}. With this, we can shift the condition a[$4] (i.e. true if it exist in r) 'out' to be the condition for determining whether we need to change $1 to "Reserved" or not.

  • Thanks guys - I've tried these and all give me this error: awk: fatal: cannot open file FileB,' for reading (No such file or directory)` P.S. Sorry for the poor formatting - can't get code to work... – Gordon Aug 13 '15 at 19:43
1

You can do it through awk:

awk -F"\t" '{if(NF==1){arr[$1]=$1}else{if(arr[$4]==$4){$1="Reserved"}{print $0}}}' fileB, FileA

The constant variable NF indicates the number of fields in file, in this code the awk will read the FileB first, and put all its data in an array called arr, in FileA, if the fourth field $4 = the array value (IP Address), then it will replace the host name with reserved.

from your samples, this will output:

Reserved IN A 10.10.20.1 
Reserved IN A 10.10.20.2 
hostname3 IN A 10.10.20.3

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.