Cut or awk in reverse

I may be making this too hard on myself, but I'm trying to find a way that I can use a cut or awk string to always remove the last two delimited fields of a string.

Say I have

PackageName-U939393-8.2.3.4.s390x.rpm

But the s390x could be any string w/o periods in it, x8664 for example, etc... I need to use cut or awk to remove the .s390x.rpm piece.

I was using '.' as the delimiter, but the number of '.' will vary.

$ echo 'PackageName-U939393-8.2.3.4.s390x.rpm' | awk -F. '{NF-=2;}1' OFS='.'
PackageName-U939393-8.2.3.4

NF is an internal variable that specifies Number of Fields. You can then access the last field as $NF, second to last as $(NF-1) etc.
Here I just decrement NF by two and set the OFS (output field separator) to '.'. The '1' is a shortcut for 'print $0'.

Could it be a sed based solution? Maybe sed suits better this kind of problem. This regular expression:

\.[^.]*\.[^.]*$

means: the last two dot delimited fields. So, we just need to use this regex into a sed substitution command:

$ echo PackageName-U939393-8.2.3.4.s390x.rpm | sed 's/\.[^.]*\.[^.]*$//'
PackageName-U939393-8.2.3.4
$ echo PackageName-U939393-8.2.3.4.x8664.rpm | sed 's/\.[^.]*\.[^.]*$//'
PackageName-U939393-8.2.3.4

Of course, awk and cut can be used too, as mirni showed us, but I think sed is simpler.

$ str=PackageName-U939393-8.2.3.4.s390x.rpm
$ echo "${str%.*.*}"
PackageName-U939393-8.2.3.4

This one is by far the fastest solution as it is based only on the shell internals :b:

Just for my personnal comprehension ... got the 1 part but not the ; in the {NF-=2;} Can somebody expain? Cause it works without it.

The semicolon is superfluous there, one could just leave it out, or even do this:

echo 'PackageName-U939393-8.2.3.4.s390x.rpm' | awk -F. NF-=2 OFS=.

That is what i tough. Even for leaving out the 1 cause the default action is print $0 but i was only wondering what is reasoning was for putting a ; into those brackets.

One would use it to separate commands, but there is not command after the semicolon so it can be left out.

1 Like

Thanks for all the responses, I went the awk route before the other ones and the awk one definitely works. Haven't tested the others, but I'll probably use the shell only one, just b/c that's what I generally do and it should be faster.

Thanks