0

I have been trying this many ways, but still cannot achieved what I want. Sorry i'm still learning.

What I want is like this:

File A.txt

5844
6069
6303
6309

File B.txt

// some comment
// some  explanation
100,5,3,8,,,
500,5,44,8,,,
//2500,5,2,8,,,
2121,5,2,8,,,
5535,5,4,6069,,,
5844,1,4,5844,,,
5900,5,2,8,,,
6069,5,4,8,,,

I want to change the searched number from A.txt and comment out the line in B.txt. sometimes the searched number may appear in another column, so it will only change the first column.

Result:

// some comment
// some  explanation
100,5,3,8,,,
500,5,44,8,,,
2500,5,2,8,,,
2121,5,2,8,,,
5535,5,4,6069,,,
//5844,1,4,5844,,,
5900,5,2,8,,,
//6069,5,4,8,,,

I tried and sometimes it got mess up and changed the other column also. Then I used something like this, its very long and not easy to modified,

awk -F ',' '/^5844/ && $1="5844"{$1="//5844"}1' b.txt > c.txt; cp c.txt ba.txt; rm -rf b.txt; mv ba.txt b.txt

and it's also sometimes remove the ',' separator.

Please help, thank you very much.

1
  • General note on safety: never run rm -rf if it isn't necessary. To delete a regular file, you don't need -r or -f so just run rm alone.
    – terdon
    Mar 9, 2020 at 13:25

1 Answer 1

4
$ awk -F , 'FNR==NR { data[$1]=1; next } $1 in data { $0 = "//" $0 }; 1' 'File A.txt' 'File B.txt'
500,5,4,8,,,
5535,5,4,6069,,,
2121,5,4,8,,,
//5844,5,4,5844,,,
//6069,5,4,8,,,

What I'm doing here is first reading in the numbers from File A.txt as keys in the associative array data. I then test each first field from File B.txt to see whether it's a key in data or not. If it is, I prepend // to the current line. All lines, whether modified or not, are then printed.

The FNR==NR test will only ever be true while reading from the first file on the command line, and the block finishes with next. This means that the first block is executed for the first file only, while the second block is executed for the second file, if the first field is a key in the data array.

The 1 at the end triggers the output and could be replaced by { print }.

The above will only add // to the lines in the second files matching the numbers in the first file. To also remove // from lines not matched (i.e. to handle your updated question):

$ cat 'File B.txt'
// some comment
// some  explanation
100,5,3,8,,,
500,5,44,8,,,
//2500,5,2,8,,,
2121,5,2,8,,,
5535,5,4,6069,,,
5844,1,4,5844,,,
5900,5,2,8,,,
6069,5,4,8,,,
$ awk -F , 'FNR==NR { data[$1]=1; next } FNR > 2 { if ($1 in data) $0 = "//" $0; else sub("^//","") }; 1' 'File A.txt' 'File B.txt'
// some comment
// some  explanation
100,5,3,8,,,
500,5,44,8,,,
2500,5,2,8,,,
2121,5,2,8,,,
5535,5,4,6069,,,
//5844,1,4,5844,,,
5900,5,2,8,,,
//6069,5,4,8,,,

The awk command assumes that you want to pass the first two lines of File B.txt through unchanged (this is what the FNR > 2 test takes care of). The FNR > 2 block tests whether the number is a key in data or not, and if it is, the line is commented out, but if it isn't, any // at the start of the line is removed using sub().

Instead of FNR > 2 you could use /^\/\/ / to test for a comment at the top of the file. This would require that all such comments always start with // followed by a space.

The special variables NR and FNR holds the number of lines read so far in total (NR) and in the current file (FNR).


The commas would "disappear" if I changed only the first field with $1 = "//" $1 as that would re-form the record using the current value of OFS (a space by default). You could prevent this by using BEGIN { OFS=FS }, which would set OFS to the comma character (or whatever character you use with -F on the command line).

7
  • Does it need to be data[$1]=1; next? Wouldn't just data[$1]; next be sufficient?
    – guest
    Mar 9, 2020 at 13:09
  • @guest Possibly, if you're tired of typing, yes. I think that should work, but as I'm not 100% certain it works everywhere I opted for setting a value.
    – Kusalananda
    Mar 9, 2020 at 13:12
  • I'm sorry sir, i think my question is a bit wrong, should i change the main post? file A.txt and B.txt content does not have the same line number, and means a.txt record may be in random position. i tried your solution but it did'nt work, apparently FNR==NR compare if the record is on the same line am i right? any ways thanks Mar 9, 2020 at 13:16
  • 1
    Thanks so much sir with detailed explanation as well, i tried doing many days already by searching around the forum, but still can't make it the way i want, and yours only using one line :D Guess i did learn something here and there, glad i ask a question here, it solved instantly.. Mar 9, 2020 at 13:46
  • 1
    @guest - yes, data[$1]; next is all you need and will work in any awk. Using data[$1]=1 may just take up more memory, depending on how the arrays are implemented.
    – Ed Morton
    Mar 10, 2020 at 18:49

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .