This will do what I think you are asking for. It collects all values from the 4th column and then, for all lines in the file and all values seen on the fourth column, it will print the line if any of the 4th values are between the values on the line.
perl -lane '$want{$F[$#F]}++; foreach $wanted (keys(%want)){
if($wanted > $F[1] && $wanted < $F[2]){print "@F[0..2]"}
}' file
A 1 10
C 100 1000
D 1000 10000
However, as you can see above, this does not produce the output you show. It is printing line C
because 100 < 120 < 1000 and it is not printing line E because none of the values of the 4th column are between 10000 and 100000.
Explanation
The -a
switch to perl
makes it automatically split the input file into fields on whitespace and saves the fields as the array @F
. So, I save the last field ($F[$#F]
) in the %wanted
hash, and for each line, I go through the keys of the hash I have so far and print the 1st through 3rd fields (@F[0..2]
) of the line if any of them are between the values.
Note that this will not work if your file is not ordered, if one of the 4th column numbers can appear after a line it would satisfy. If that can happen, you need to read the file twice, something like this:
perl -le 'open(A,"$ARGV[0]"); while(<A>){@F=split(/\s+/); $want{$F[$#F]}++};
open(A,"$ARGV[0]"); while(<A>){@F=split(/\s+/);
foreach $wanted (keys(%want)){
if($wanted > $F[1] && $wanted < $F[2]){print "@F[0..2]"}
}} ' file
Or, you can use @Stephane's answer which also reads the file twice.
100 1000 300
on the 3d line and200 1000
on the second? Or can I safely assume that the numbers are always incrementing and I don't need to read the whole file twice to get them all? Also, according to your description, you should also want columnC
since 100 < 120 < 1000 and I don't see why you're printing column E in your example.