sunshine737
sunshine737

Reputation: 61

Extract substring after a character

I'm trying to extract substring after the last period (dot). examples below.

I tried below. but works only if the character(dot) exists once. But my filename may have (dot) for 0 or more times.

echo "filename.txt" | cut -d "." -f2

Upvotes: 0

Views: 15051

Answers (4)

ghoti
ghoti

Reputation: 46836

One can make this portable (so it's not Linux-only), avoiding an ERE dependency, with the following:

$ sed -ne 's/.*\.//p' <<< "file..txt"
txt
$ sed -ne 's/.*\.//p' <<< "file.txt."

$ sed -ne 's/.*\.//p' <<< "file"
$ sed -ne 's/.*\.//p' <<< "file.xml"
xml

Note that for testing purposes, I'm using a "here-string" in bash. If your shell is not bash, use whatever your shell uses to feed data to sed.

The important bit here is the use of sed's -n option, which tells it not to print anything by default, combined with the substitute command's explicit p flag, which tells sed to print only upon a successful substitution, which obviously requires a dot to be included in the pattern.

With this solution, the difference between "file.txt." and "file" is that the former returns the input line replaced with null (so you may still get a newline depending on your usage), whereas the latter returns nothing, as sed is not instructed to print, as no . is included in the input. The end result may well be the same, of course:

$ printf "#%s#\n" $(sed -ne 's/.*\.//p' <<< "file.txt.")
##
$ printf "#%s#\n" $(sed -ne 's/.*\.//p' <<< "file")
##

Upvotes: 2

fedorqui
fedorqui

Reputation: 289555

Let's use awk!

awk -F"." '{print (NF>1)? $NF : ""}' file

This sets field separator to . and prints the last one. But if there is none, it prints an empty string.

Test

$ cat file
filename..txt
filename.txt.
filename
filename.xml
$ awk -F"." '{print (NF>1)? $NF : ""}' file
txt


xml

Upvotes: 5

Walter A
Walter A

Reputation: 19982

Use sed in 2 steps: first remove string without a dot and than remove up to the last dot:

sed -e 's/^[^.]*$//' -e 's/.*\.//'

Test:

for s in file.txt.. file.txt. file.txt filename file.xml; do
   echo "$s -> $(echo "$s" | sed -e 's/^[^.]*$//' -e 's/.*\.//')"
done

Testresult:

file.txt.. ->
file.txt. ->
file.txt -> txt
filename ->
file.xml -> xml

Actually the answer of @ghoti is roughly the same, just a bit shorter (better). This solution can be used by other readers who wants to do something like this in another language.

Upvotes: 0

Vampiro
Vampiro

Reputation: 335

Simple to do with awk:

awk -F"." '{ print $NF }'

What this does: With dot as a delimiter, extract the last field from the input.

Upvotes: 0

Related Questions