Assuming I have this string :
blabla1 blabla2#blabla1 blabla2#blabla1 blabla2#blabla1 blabla2#blabla1 blabla2
I can get this part :

Via [^#]+$
(test)
Visualize :

Question :
How can I get (using regex) the other part (excluding last #) ?

Assuming I have this string :
blabla1 blabla2#blabla1 blabla2#blabla1 blabla2#blabla1 blabla2#blabla1 blabla2
I can get this part :

Via [^#]+$
(test)
Visualize :

Question :
How can I get (using regex) the other part (excluding last #) ?

I guess, with a lookahead
(.*)(?=#[^#]+$)
[^#] can also be used to "not containing the word "abc" ? I mean - is this valid [^(abc)] ?[...] always matches a single character.# , there was #abc ?/(.*)#[^#]*$/
The result is your first capture, not the whole match.
/(.*)#[^#]*$/.exec("foo#bar baz#qux quz")[1] === "foo#bar baz"
Even better:
/^(.*)#([^#]*)$/
If you're sectioning the string for some purposeful activity, you probably don't actually want to drop the last pound and text that follows it - you just need to process it separately. Even if you want the procedures that handle each part to split it up separately (e.g. so you can pass them the same string instead of an array), you do not want to have a regex - any part of any regex - appear twice in your source. They tend to be write-only and error-prone, so every place it appears is something you will probably re-write and possibly mess up when you go to revise it.
That's why I wouldn't do forward assertions - the regex to retrieve the text beyond the last # will be identical to the one you use to get the text before it, but the forward assertion will be substituted so that the last part is part of the match. I usually don't section strings that have unimportant parts, so I want the match to be the whole string, with the parts I need to examine separately in separate captures.
From the perspective that this task is entirely an exercise, it's still important to know that, in addition to matching what you want, you can also use regex to match what you don't want and capture the rest.