Столбец печати, если значения находятся между двумя другими значениями

Я довольно новичок в анализе данных, и у меня есть проблема с фильтрацией некоторых моих значений. У меня есть данные, упорядоченные в файле с четырьмя столбцами:

A 1 10 5 B 10 100 120 C 100 1000 1200 D 1000 10000 E 10000 100000 F 100000 1000000 G 1000000 10000000 

Теперь я хочу напечатать только строки, где значения в столбце 4 находятся между значениями в столбцах 2 и 3. Итак, что-то вроде этого:

 A 1 10 C 100 1000 D 1000 10000 

Я пытался использовать grep и awk, например awk '$4 >= $2 && $4 <= $3 {print $1,2,3}' . Хотя проблема заключается в том, что awk ищет только в одной строке, а не для всех строк, где он соответствует этим критериям. Я думаю, это довольно просто, но я не мог понять, как это сделать.

Это будет делать то, о чем я думаю, что вы просите. Он собирает все значения из 4-го столбца, а затем для всех строк в файле и всех значений, видимых в четвертом столбце, он будет печатать строку, если любое из 4-х значений находится между значениями в строке.

 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 

Однако, как вы можете видеть выше, это не дает вывод, который вы показываете. Это линия печати C потому что 100 <120 <1000 и не печатает строку E, потому что ни одно из значений 4-го столбца не находится между 10000 и 100000.


объяснение

Переключатель -a на perl позволяет автоматически разбивать входной файл на поля в пробеле и сохраняет поля в виде массива @F . Итак, я сохраняю последнее поле ( $F[$#F] ) в %wanted hash, и для каждой строки я просматриваю ключи хэша, которые у меня есть до сих пор, и печатаю от 1 до 3 полей ( @F[0..2] ) линии, если любое из них находится между значениями.

Обратите внимание, что это не будет работать, если ваш файл не упорядочен, если один из 4-го столбца может появиться после строки, которую он удовлетворит. Если это может произойти, вам нужно дважды прочитать файл, что-то вроде этого:

  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 в  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 в  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 

Или вы можете использовать ответ @ Stephane, который также дважды читает файл.

 awk 'NR == FNR {if (NF >= 4) a[$4]; next} {for (i in a) if (+i >= $2 && +i <=$3) {print $1, $2, $3; next}}' file file 

что-то вроде этого?

 awk '$4 <= $3 && $4 >= $2' data A 1 10 5 

без четвертой колонки:

 awk '($4 <= $3 && $4 >= $2){print $1,$2,$3}' data A 1 10