steeldriver has already provided an awk solution. Here's a perl version (using an array slice rather than a for loop):
$ perl -lane 'print if ($.==1 || grep ($_ >= 2, @F) == $#F)' input.txt
name v1 v2 v3 v4
g2 10 3 5 2.3
g3 7 2.5 2.8 3.9
This prints only the first (header) line and lines where all numeric fields have a value greater than or equal to 2. (non-numeric fields like g1
or g2
will evaluate to 0
)
Note: perl's grep()
function is similar in concept, but not exactly the same as the grep
command-line program.
grep(expression,array)
runs the expression in its first argument (e.g. $_ >= 2
) against every element of an array (e.g. @F
), and returns an array consisting of every element where the result was true.
In a scalar context (such as a numeric comparison against an integer), it returns the number of times the expression was true, instead of an array. This is what we are doing here with == $#F
, to test equivalence with $#F
(the number of elements in array @F
)
The expression can be a simple test as used in this example, or a code block containing any perl code. It can also optionally modify each element. e.g. @new = grep(s/foo/bar/g, @old)
would populate @new with all elements from @old which were successfully modified (i.e. thost that contained at least one "foo". all of which were changed to "bar"). See perldoc -f grep
for details.