1

I have a text file which contains 7 columns of floating point values (). I would like to use perl one-liner and find the values which are greater than a threshold in the 7th column. Then, I want to replace the values of 4th, 5th, 6th, 7th in the rows whose 7th column's value exceed the threshold with 0.00000000. Could someone please let me know how I can do that?

Here is an example. Let's assume the threshold is 1.00000.

  0.04718683      0.24081557      0.02831210      0.98316791      0.00000000     -0.98446111      1.39132413
  0.05662420      0.24081557      0.02831210     -0.00006975      0.00001697     -0.00144172      0.00144350
  0.06606157      0.24081557      0.02831210      0.00039672      0.00007192     -0.00001264      0.00040339
  0.07549894      0.24081557      0.02831210      0.00087559      0.00010765     -0.00028455      0.00092694
  0.08493630      0.24081557      0.02831210      0.00004609      0.00012754     -0.00030319      0.00033214
  0.09437367      0.24081557      0.02831210     -0.00038816      0.00008384      0.00011519      0.00041348

In the first line, column 7th has a value greater than threshold, 1.39132413 > 1.00. Therefore, the first line needs to be replaced with the following (zero values) and all other lines remain intact as they don't meet the criteria.

  0.04718683      0.24081557      0.02831210      0.00000000      0.00000000     0.00000000   0.00000000
3

If you don't need to keep the whitespace exactly the same, this works:

$ perl -lane 'do{$_=sprintf("%.8f",0) for @F[3..6]} if $F[6]>1; print "@F"' file 
0.04718683 0.24081557 0.02831210 0.00000000 0.00000000 0.00000000 0.00000000 
0.05662420 0.24081557 0.02831210 -0.00006975 0.00001697 -0.00144172 0.00144350
0.06606157 0.24081557 0.02831210 0.00039672 0.00007192 -0.00001264 0.00040339
0.07549894 0.24081557 0.02831210 0.00087559 0.00010765 -0.00028455 0.00092694
0.08493630 0.24081557 0.02831210 0.00004609 0.00012754 -0.00030319 0.00033214
0.09437367 0.24081557 0.02831210 -0.00038816 0.00008384 0.00011519 0.00041348

To skip a certain number of lines, just test for the value of $. (the current line number):

$ perl -lane 'do{$_=sprintf("%.8f",0) for @F[3..6]} if $F[6]>1 && $.>3; print "@F"' file 
  • Thanks. Whitespaces are not important for me. Is is also possible to skip the first three lines in the text file and then perform this operation? – AFP Sep 29 '14 at 22:48
  • 1
    @A2009 sure, just add && $. >3 before the print call. See update. – terdon Sep 29 '14 at 22:50
  • 1
    +1. An even more elegant way to do the zeroing: map {$_=sprintf ".8f",0} @F[3..6] – Joseph R. Sep 30 '14 at 1:57

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.