Bash get file name and extension name separately without using awk, basename or shell parameter

assuming i have a file which is called
my.file.name.txt
and i would like to get the file name which is
my.file.name

and extension
.txt

separately

without using awk or basename , or shell parameter
other commands are allowed to be used such as cut , grep , tail , tr and more could be used

i tried to use
echo a.b.c.d | grep -o “[.]” | wc -l
but it gives 3 which is wrong. I tried to get the number of parts (fields/columns) then cut according to number of fields/columns

There is a good reason we use bash shell parameters, basename, or filename. It makes life easier because the filename and extension length varies. Then, of course, you can use sed or grep with regex:

file="my.file.name.txt"
echo "$file" | sed 's/\.[^.]*$//'
echo "$file" | sed 's/^.*\.//'

Grep example:

file="name.txt"
echo "$file" | grep -o '[^.]*$'
echo "$file" | grep -o '^[^.]*'

The goal of programming and commands is to keep it simple so that you can understand what is going on when you read the commands or script in the next ten years again.

There are 3 dots in a.b.c.d, so you got correct answer as three.

echo "$file" | grep -o '^[^.]*'

returns only my while it should return my.file.name

What about?

file="my.filename.foo.txt"
echo "$file" | grep -Po '.*(?=\.)'
echo "$file" | grep -o '[^.]*$'

The regex .*(?=\.) matches zero or more chars (.) followed by a dot (\.), but only outputs the characters before the dot (.*). The (?=\.) is a positive lookahead, which asserts that a dot (\.) follows the characters without actually matching it. This is Perl-compatible regular expressions and well defined in Perl manual pages

man 3 pcre

Can you please add formatting to your posts? All code must be put between ``` and ```. Like:
```
# Your code here
echo “$file” | grep -o ‘^[^.]*’
```
And it will show it as follows:

# Your code here
echo "$file" | grep -o '^[^.]*'