Bash – how to use regex in alias

aliasbashregular expression

I want to create the alias for the command "ssh user@10.32.44.225" as 10.32.44.225

alias [0-9][0-9][0-9].[0-9][0-9][0-9].[0-9][0-9][0-9].[0-9][0-9][0-9]="ssh user@$0"

I have created it, but it is not working. Is there any syntax error in this command?

Best Answer

This is doable - even with alias, though the only way I know would involve eval which can be dangerous depending on what the arguments might contain - but not with regex. The real problem here is tokenization - for each simple command the shell reads in it attempts to execute whatever word it finds in command position as an alias first, then. failing that, as a function/builtin, and, failing both of those, as a $PATHed executable. This is a simplification of the process, but it is pretty close to the truth.

The problem is that you have in a single word two possible tokens - ssh is what you'd like to execute, and @$IP is an argument with which you'd like to execute it. You can do as has been elsewhere suggested and simply split the token in two combined with a shell function - this is simply done. Or you can get the first token to split itself.

An interesting thing about shell $var names is they are pretty explicit about what characters they can contain. Save a single special case, @ is not among those. If I do:

$var_this_is_appended_to_the_name

The shell will interpret the entire string as a single variable name because all of the characters within are allowable within a $var name. But...

$var@this_is_appended_to_the_name

...results in two tokens (if not necessarily two words) and the shell expands $var independently of @the_rest. Alias expansion, unfortunately, has no such convenient marker as $ and so the shell will always attempt to expand either...

alias@this_is_appended; alias_this_is_appended

...as a single token. It is also because the shell expands both $var and aliased cmdstring simultaneously that the latter cannot be contained within the former and still be executed without eval - but then any arguments given $var - even ${varcontains='$(cmd substitutions)'} will be evaluated twice - which can be fairly dangerous.

So I propose you do something with a readonly variable named $ssh that looks like this:

ssh() { case "$1" in
(@*)  set -- "$USER$@";;
esac; command -p ssh "$@"
}

readonly ssh='ssh '

That way you can do...

$ssh@someplace.com; $ssh@000.000.000.000

...or...

ssh @someplace.com

...and etc. or whatever, because the shell will split out the two tokens which are $ssh and @somplace.com into two words. It does not work, however, if you...

"$ssh@someplace.com"

...because in that case, though you get two tokens, the result is still single word. I used readonly above to ensure that the $ssh varname cannot be sabotaged and reset to something more dangerous, but this might still be possible to do with the ssh function for any normal user in the shell. I'm unaware of any means that can be used to readonly a shell function, but, if this is a concern for you, then you may want to locate the function in a $PATHed shell script with appropriate read/write rights.

Then again, it can work without a function at all if set from a profile file or whatever:

[mikeserv@localhost ~]$ readonly "ssh=ssh $USER"
[mikeserv@localhost ~]$ $ssh@localhost
mikeserv@localhost's password: 

But it is less flexible that way.

Related Question