如何在zsh中source依赖bash特性的bash脚本?
解决bash脚本source到zsh环境的方法
因为bash和zsh的子进程环境无法直接共享给父进程,所以不能通过启动bash再exec zsh的方式(exec后的zsh是bash的子进程,环境变量带不回原来的zsh)。正确的思路是让bash执行脚本后,将所有环境变量输出为可被zsh执行的命令,再在当前zsh会话中执行这些命令。
方法一:直接提取环境变量并导入
可以用下面的函数实现:
function source-bash() { bash -c "source $1; env" | while read line; do if [[ $line =~ ^[A-Za-z_][A-Za-z0-9_]*= ]]; then export "$line" fi done }
使用方式:
source-bash t.bash
原理说明
bash -c "source $1; env":启动bash并source目标脚本,然后输出所有环境变量- 循环读取每一行输出,筛选出符合环境变量格式的行,用
export导入到当前zsh会话中
方法二:更精准的环境变量对比
如果脚本只修改了部分环境变量,可以先记录source前的环境变量,对比后只导入变化的部分,避免冗余:
function source-bash() { local before_env=$(env | sort) local after_env=$(bash -c "source $1; env" | sort) comm -13 <(echo "$before_env") <(echo "$after_env") | while read line; do if [[ $line =~ ^[A-Za-z_][A-Za-z0-9_]*= ]]; then export "$line" fi done }
为什么之前的方法不行
- 第一个函数的引号嵌套错误:
bash -c "'$@ ; exec zsh'"中,单引号会把$@展开后的内容和; exec zsh包裹,但如果脚本名带空格或者特殊字符,会导致引号不匹配,触发语法错误。而且即使成功,exec后的zsh是bash的子进程,环境变量无法传递回原来的zsh会话。 - xargs的方法同样是启动子bash进程,子进程的环境变量无法影响父zsh进程,所以脚本设置的变量不会在当前zsh中生效。
内容的提问来源于stack exchange,提问作者너를 속였다
相关产品推荐
相关产品推荐

