如何执行双引号内的函数?

如何执行双引号内的函数?

我有这些功能:

#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 启动之前,它就在此处展开​​。因此,无论它是否正确导出,它都会运行。尽管即使它在命令替换内部工作,它也不会执行您想要的操作,因为它会在编译器之前运行。

相关内容