如何在管道至yad进度条的进程外部保留其内定义的变量?
解决管道子进程变量无法被父进程访问的问题
原代码中管道会创建子shell,子shell内定义的变量无法传递到父shell环境,所以echo $a会输出空值。要在不使用临时文件的前提下解决这个问题,可以用以下几种重定向/进程替换的方法:
方法1:进程替换替代管道
把管道替换为进程替换(>(...)),让左侧命令在当前shell执行,而非子shell:
a=3; sleep 1 > >(yad --progress --auto-close) echo $a
>(yad ...)会创建一个临时文件描述符,将sleep 1的输出(如果有的话)定向到yad的标准输入,而a=3是在当前shell环境中执行的,后续echo $a可以正常读取变量值。
方法2:使用文件描述符定向输出
如果需要在代码中多次向yad发送进度数据,可通过自定义文件描述符实现:
# 创建文件描述符3,指向yad的输入 exec 3> >(yad --progress --auto-close --percentage=0) # 在当前shell定义变量 a=3 declare -A complex_arr=(["name"]="test" ["content"]="multi line string") # 向yad发送进度数据 echo "30" >&3 sleep 0.5 echo "70" >&3 sleep 0.5 echo "100" >&3 sleep 0.5 # 关闭文件描述符 exec 3>&- # 正常访问变量 echo $a echo ${complex_arr["content"]}
方法3:代码块+进程替换
如果逻辑需要放在代码块中,用花括号{}(当前shell代码块,非子shell)替代子shell括号(),再通过进程替换定向输出:
{ # 在当前shell定义任意类型变量 a=3 multi_line_str="line1 line2 line3" arr=("elem1" "elem2" "elem3") # 向yad发送进度信息 echo "25" sleep 0.5 echo "50" sleep 0.5 echo "75" sleep 0.5 echo "100" } > >(yad --progress --auto-close --percentage=0) # 直接访问变量 echo $a echo "$multi_line_str" echo ${arr[@]}
以上方法的核心是避免管道创建的子shell隔离,让变量定义在当前shell环境中,因此数组、关联数组、多行字符串等复杂类型变量都可以直接被后续代码访问,无需序列化到临时文件再重构。
内容的提问来源于stack exchange,提问作者ChameleonScales
相关产品推荐
相关产品推荐

