我有这些功能:
#execute vim and then exit on err return
ve() {
vim "$@" || exit
}
export -f ve
#compile c source -> asm source in new tab in xfce terminal
casm() {
[ -z ${1} ] && return
fname=$1
xfce4-terminal --tab -e "bash -c "\""gcc -S $fname.c; ve $fname.s ;exec bash \""
}
export -f casm
在这种情况下,ve
函数 ("vim and exit" == "ve") 在第二个双引号中调用(请参见此处:)gcc -S $fname.c; ve $fname.s ;exec bash
。问题是 bash 会给出 err bash: ve: command not found
(我export
后来得到了它,如你所见),我不知道我还应该做什么来使它更明显。
对于第二次尝试,我尝试过:
#compile c source -> asm source in new tab in xfce terminal
casm() {
[ -z ${1} ] && return
fname=$1
xfce4-terminal --tab -e "bash -c "\""gcc -S $fname.c; $(ve $fname.s) ;exec bash \""
}
export -f casm
也就是说 - 使命令成为子 shell,但是当尝试打开它时 -> Vim: Warning: Output is not to a terminal
,这会使终端崩溃。那么问题是,如何将全局函数嵌入双引号中并使其安全?
答案1
您的第一个解决方案在我的系统上完美运行。
尝试在另一个系统上测试它:您的系统上可能有一些问题。
在第二个示例中,您可以强制vim
使用/dev/tty
:
ve() { vim "$@" </dev/tty >/dev/tty || exit; }
答案2
在 Xubuntu 上尝试这个,似乎 xfce4-terminal 实际上并没有启动一个新进程来运行新的终端窗口。相反,它只是调用现有流程来创建它。我在不同窗口中启动的 shell 都是同一个 xfce4-terminal 进程的子进程。
这意味着用于传递函数的环境变量无法传递到新 shell,因为它不是第一个 shell(导出函数的 shell)的子代。如果您没有运行 xfce4-terminal 的副本,那么它会启动一个新进程,并且环境变量会正常传递。或者,如果您运行例如 xterm,因为它总是创建一个新进程。
这与评论中链接的 Kusalananda 问题相似但不同,图形登录时如何从.profile导出函数,但相同的解决方案应该有效:
相反,将函数定义放入其中~/.bashrc
,它应该被此处启动的 shell 读取。如果没有,那么您必须在内壳中显式地执行此操作bash -c '. ~/.bashrc; gcc ...'
。
在你的第二个片段中:
xfce4-terminal --tab -e "bash -c "\""gcc -S $fname.c; $(ve $fname.s) ;..."
命令替换用双引号括起来,因此在 xfce4-terminal 启动之前,它就在此处展开。因此,无论它是否正确导出,它都会运行。尽管即使它在命令替换内部工作,它也不会执行您想要的操作,因为它会在编译器之前运行。