'How to "give priority" to certain pattern instead of others in sed?

I have this sed filter:

/.*[1-9][0-9][0-9] .*/{
        s/.*\([1-9][0-9][0-9] .*\)/\1/
}

/.*[1-9][0-9] .*/{
        s/.*\([1-9][0-9] .*\)/\1/
}

/.*[0-9] .*/{    # but this is always preferred/executed
        s/.*\([0-9] .*\)/\1/
}

The problem is that the first two are more restrictive, and they are not executed because the last third one is more "powerfult" because it includes the first two. Is there a way to make sed take the first two, with a "priority order"? Like

if the first matches
    do first things
elif the second matches
    do second things
elif the third matches
    do third things
sed


Solution 1:[1]

This might work for you (GNU sed):

sed -E 's/(^|[^0-9])([1-9][0-9]{,2}|[0-9]) .*/\n\2\n/;s/.*\n(.*)\n.*/\1/' file

I assume you want to capture a 1,2 or 3 digit number followed by a space.

Alternation | works left to right.

The above regexp will capture the first match or just return the whole string.

N.B. The ^|[^0-9] is necessary to restrict the match to a 1,2 or 3 digit number.

If the required string occurs more than once in a line the match may be altered to the nth match,e.g the second:

sed -E 's/(^|[^0-9])([1-9][0-9]{,2}|[0-1]) .*/\n\2\n/2;s/.*\n(.*)\n.*/\1/' file

The last match for the above situation is:

sed -E 's/(^|.*[^0-9])([1-9][0-9]{,2}|[0-1]) .*/\n\2\n/;s/.*\n(.*)\n.*/\1/' file

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1