如何在别名中使用正则表达式?

如何在别名中使用正则表达式?

我想为命令“ssh”创建别名[电子邮件受保护]“如 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"

我已经创建了它,但它不起作用。这个命令有语法错误吗?

答案1

Bash 别名不要那样做- 它们是简单的字符串,没有 shell 元字符,也没有通配符。您可以通过大量的努力使调试挂钩执行您想要的操作(从这个超级用户问题),但您可能会更好地适应键入额外的几个字符并定义一个单参数函数s或其他东西:

s() {
    ssh user@"$1"
}

然后:

s 127.0.0.1

会跑:

ssh [email protected]

从技术上讲,定义单独的别名或制作单独的 shell 脚本来执行您想要的操作是可行的,但可能的地址有 2^32 个,因此它实际上并不可行。如果您想要使用的地址数量很少,并且您事先知道它们,则可以直接执行此操作。

答案2

如果您使用bash4 或更高版本,则可以利用该command_not_found_handle钩子,因为裸 IP 地址极不可能是有效的命令名称。将其添加到您的.bashrc文件中:

command_not_found_handle () {
    if [[ $1 =~ [0-9][0-9][0-9]\.[0-9][0-9][0-9]\.[0-9][0-9][0-9]\.[0-9][0-9][0-9] ]]; then
        ssh user@$1
    else
        printf "Command not found: %s\n" "$1" >&2
        return 127
    fi
}

如果缺少的命令与 IP 地址的正则表达式匹配,它将改为运行所需的ssh命令;否则,它会模仿丢失命令的默认行为。

答案3

别名中没有模式匹配。因此,如果您想在192.168.0.2不输入内容的ssh user@情况下登录,则必须指定:

alias 10.32.44.225="ssh [email protected]"

对于您可能使用的每个 IP 地址。

当然,您可以编写一个程序来根据您需要的范围写出这些行。或者做类似的事情:

for i in $(seq 225 228); do
    alias 10.32.44.$i="ssh [email protected].$i"
done

获取范围的别名10.32.44.22510.32.44.228

答案4

这是可行的 - 即使使用alias,尽管我知道的唯一方法会涉及到evalwhich 可能是危险的,具体取决于参数可能包含的内容 - 但不能使用正则表达式。真正的问题是代币化- 对于 shell 读取的每个简单命令,它会尝试执行任何操作单词它发现在指挥位置首先作为别名,然后。如果做不到这一点,则作为函数/内置函数;如果两者都失败,则作为$PATHed 可执行文件。这是过程的简化,但非常接近事实。

问题是你有一个单一的单词两种可能代币-ssh是你想要执行的,并且@$IP与哪个论证你想执行它。您可以像其他地方建议的那样,简单地将令牌分成两部分并结合 shell 函数 - 这很容易完成。或者你可以获得第一个令牌分裂自身

关于 shell$var名称的一个有趣的事情是它们非常明确地说明了它们可以包含哪些字符。保存一个特殊情况,@不在其中。如果我做:

$var_this_is_appended_to_the_name

shell 会将整个字符串解释为单个变量名称,因为名称中允许使用其中的所有字符$var。但...

$var@this_is_appended_to_the_name

...结果是两个令牌(如果不一定是两个并且壳的膨胀$var独立于@其余的部分。不幸的是,别名扩展没有这样方便的标记,$因此 shell 总是会尝试扩展...

alias@this_is_appended; alias_this_is_appended

...作为单个令牌。也正是因为 shell 同时扩展了两者,$var所以aliased cmdstring后者不能包含在前者中,并且仍然可以在没有给定参数的情况下执行eval- 但随后给出的任何参数$var- 甚至${varcontains='$(cmd substitutions)'}都会被评估两次- 这可能相当危险。

所以我建议你用一个名为如下的readonly变量做一些事情:$ssh

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

readonly ssh='ssh '

这样你就可以做...

[email protected]; [email protected]

...或者...

ssh @someplace.com

...等等等等,因为 shell 会将两个标记$ssh分成@somplace.com两个。然而,它不起作用,如果你...

"[email protected]"

...因为在这种情况下,虽然你得到两个标记,但结果仍然是单个单词。我readonly在上面使用了确保varname 不会被破坏并重置为更危险的内容,但这对于 shell 中的任何普通用户来说$ssh仍然可以使用该函数来完成。ssh我不知道有什么方法可以用于readonlyshell 函数,但是,如果您担心这一点,那么您可能希望在$PATH具有适当读/写权限的 ed shell 脚本中找到该函数。

话又说回来,如果从配置文件或其他文件中设置,它可以在没有函数的情况下工作:

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

但这样灵活性较差。

相关内容