有没有办法显示别名后bash 已经进行了替换吗?
背景:
我有一个很长的别名,可以对目录执行操作。
alias do_it='cd my_working_dir; do_stuff'
这工作正常,但别名很长并且my_working_dir
经常更改。我没有对我的别名进行深入搜索以查找所有出现的my_working_dir
,而是更改为:
MY_WORKING_DIR=some_dir
alias do_it='cd ${MY_WORKING_DIR}; do_stuff'
这很好用。
但是,有时我想即时对别名进行一些细微的更改。通过之前的别名构造,我能够输入alias
、复制/粘贴我想要的命令、制作 mods 并执行。使用这种替换,当我输入时alias
我得到:
do_it='cd ${MY_WORKING_DIR}; do_stuff'
现在我必须手动替换MY_WORKING_DIR
.有没有一种方便的方法来获取别名的副本后bash 已进行替换(在本例中替换为${MY_WORKING_DIR}
.
澄清:我的目标不是更改别名/函数的输入。我希望显示生成的别名/函数已经进行替换这样我就可以复制/粘贴该输出以创建更复杂的命令。我还没有找到一种方法来显示别名或已进行替换的函数。
附加示例
TARGET_DIR='my_dir'
alias do_it='cd ${TARGET_DIR}; run task; echo "Task done in ${TARGET_DIR}'
alias
do_it='cd ${TARGET_DIR}; run task; echo "Task done in ${TARGET_DIR}'
如果我想重复别名 50x,我可以复制别名输出,然后将其粘贴到以下行中:
for i in {1..50}; do <paste_here>; done
但这是行不通的,因为alias
输出导致 ${TARGET_DIR} 未解析。
使用函数代替别名也不起作用,因为declare
同样不能替换 ${TARGET_DIR}。
这是一个简化的示例。我使用的真正别名又长又乏味, ${TARGET_DIR} 出现了很多次,因此虽然别名/函数效果很好,但将别名输出组合成更复杂的即时命令需要我手动替换 ${TARGET_DIR } 多次。
答案1
据我所知,至少不是以安全和通用的方式。对我来说,这似乎也是一种极其奇怪的使用别名的方式。
您确定 shell 脚本不会更合适吗?放在你身上的东西$PATH
($PATH
如果需要的话可以调整)并命名do_it
东西可能需要参数。
您还可以让该脚本执行与别名相同的操作,并根据要求显示带有替换的别名命令。
如果您坚持使用别名,这是非常不安全的,因为您可能会冒着扩展超出您想要的范围、错误处理转义字符\
等的风险,但您可以执行类似以下操作:
$ alias test='echo $UID'
$ alias xalias='f(){ eval echo $(echo $(alias "$@" | sed s,\'\'',\'\\\\\\\\\\\\\'',g ) ) ; unset -f f; }; f'
$ xalias test
alias test='echo 1000'
获得正确的报价是一项令人沮丧的工作。这是通过引用单引号来实现的:'
-> \'
,然后再次引用所有内容。第一次eval
调用取消对级别的引用,此时,${VAR}
不再引用级别,因此对它们进行求值。然后echo
添加回引号,因为字符串是在子 shell 中计算的。由于间接的数量,我可能有点过于复杂了。
这仍然很脆弱,并且 bash+sed 不适合这项工作。
答案2
由于您似乎希望每隔一段时间更改一次工作目录,因此建议将别名替换为 shell 函数,该函数可以将目录路径名作为命令行参数:
do_it () {
local wd="${1:-my_working_dir}"
cd "$wd" || return
do_stuff
}
该函数采用一个可选的单个参数,即目录路径名。如果给定,函数的局部wd
变量将设置为此值。如果未给出,则将局部wd
变量设置为 static string my_working_dir
。
通过一个小的更改,您可以禁止该函数将用户留在意外的工作目录中:
do_it () {
local wd="${1:-my_working_dir}"
(
cd "$wd" || return
do_stuff
)
}
函数内部带括号的子 shell 环境(包括当前工作目录,可能由 修改cd
)不会影响调用 shell 的环境。
您可以在通常声明别名的地方声明此函数,并且可以将其用作
do_it
或者有一个论据,
do_it some/directory/path
或者,在对多个目录路径名运行它的循环中,
for target_dir in some/pattern/dir*/
do
do_it "$target_dir"
done
答案3
这是以下内容的副本:
和
事实证明,BASH 使用 readline 来处理这个问题。只需按Esc然后Ctrl-e
为了进行测试,我在 .bash_profile 中定义了以下别名:
alias cdh='cd ${HOME}'
启动一个新的 shell/终端允许我输入:
cdh
然后按: Esc Ctrl-e
readline 将命令行更新为:
cd /home/user_name
MacOS 13.2.1
iterm2 3.4.15
bash 5.1.8(1)-发布 (x86_64-apple-darwin21.2.0)
Ubuntu 20.04.5 LTS
5.0.17(1)-发布 (x86_64-pc-linux-gnu)