user3271410
user3271410

Reputation: 51

grep pattern to exclude negative numbers from file

I have been struggling trying to come up with an easier answer to this problem. But still using grep.

I want to grep out the positive (and negative numbers) of myfile.dat. Myfile.dat look like this:

-1.4987 4.1354  -8.1235
4.2322  -0.9842 -2.6845
3.6845  1.5132  -2.8452
0.0122  9.3542  -1.2354
-7.2127 -1.1253 -4.3967
0.3535  7.2416  -3.1277

No need to retain column format. So I have used the following grep patterns.

Negative numbers:

grep -E -o [-][0-9]+.[0-9]+ myfile.dat

Positive numbers (here I have to pipe all numbers into another grep):

grep -Eo [-]\?[0-9]+.[0-9]+ myfile.dat | grep -v [-]

Here comes the question! Is there a grep pattern that allows me to extract positive numbers directly, without the use of a second grep command?

This is all about the pattern, not whether I could use another command.

Upvotes: 5

Views: 4548

Answers (5)

BMW
BMW

Reputation: 45333

Ok, solution with sed, grep and pure shell have been provided, I give the awk one. In fact, I didn't get the provided answers, when the problem is regarding calculation, why use some tools which are not good for calculations.

 awk '{for (i=1;i<=NF;i++) if ($i>=0) print $i} ' file

Upvotes: 1

John B
John B

Reputation: 3646

If you want to preserve the column format, you can use a BASH read loop.

Loop through an array of each line to check and unset each element that is negative.

while read -a n; do
    for i in ${!n[@]}; do
        if [[ ${n[$i]} =~ ^- ]]; then
            unset n[$i]
        fi
    done
    if [[ -n $n ]]; then
        echo ${n[@]}
    fi
done < myfile.dat

Upvotes: 1

kkeller
kkeller

Reputation: 3247

Can you use sed instead of grep? Remove negative numbers:

sed "s/-[0-9.]*//g; s/^ //" myfile.dat

Remove each sequence of a minus sign followed by digits and dots s/-[0-9.]*//g. And to beautify remove any leading spaces which may remain s/^ //.

Keeping only the positive numbers is a bit more tricky.

sed "s/^[0-9.]*//; s/ [0-9.]*/ /g; s/^ *//" myfile.dat

Remove a digits and dots at the start of the line s/^[0-9.]*//. Replace a blank, followed by digits and dots with just the blank s [0-9.]*/ /g. And finally the beautification again, to remove any remaining leading blanks at the start of the line s/^ *//. (Possibly there is a simpler way for this, but can't see it at the moment.)

Upvotes: 1

grebneke
grebneke

Reputation: 4494

You could match on beginning-of-line or space before digits:

$ grep -oE '(^| )[0-9]+\.[0-9]+' Myfile.dat | tr -d ' '
4.1354
4.2322
3.6845
1.5132
0.0122
9.3542
0.3535
7.2416

tr -d ' ' just removes any initial spaces from the output, you can skip it if not needed.

Upvotes: 2

anubhava
anubhava

Reputation: 786091

Using grep -P you can do this to get all positive numbers:

 grep -oP '(?<!-)\b[0-9]+\.[0-9]+\b' file

Upvotes: 3

Related Questions