Your solution is a function (archive). A function knows the execution context it was used in, so you can for example do this (assuming you want to do something for the player "Horst" and at his position):
/execute as Horst at @s run function test/whatever
Then, in the function, have commands like these:
say Hi, everyone!
tp @s 0 100 0
execute as @e[distance=..30] say Hi, @p[sort=nearest,limit=1]!
The first command makes Horst say "Hi, everyone!", the second command teleports Horst to 0 100 0 and then the third command causes every entity within 30 blocks around the original execution position (not around the new position that he got teleported to and also not around the command block, if you're even using one) answer with "Hi, Horst!". The location for that
@p[sort=nearest,limit=1] selector is still the one from the
/execute command that the function was called with.
You can also call another function with a different execution context with this and once that function ends, return to the first function, which still has its execution context saved.
You can even go so far with this execution context memory that you can do raycasting (which used to be done by teleporting a dummy entity forwards a bit over and over) without needing any entities: https://gaming.stackexchange.com/a/362596/171580