如何运行Bash别名时自动回显别名文本且避免管道问题?
解决Bash别名参与管道时输入被echo接收的问题
出于学习目的,希望每次运行Bash别名时自动打印别名内容,以此理解命令参数和管道逻辑。手动执行type alias-name可查看别名,但希望实现自动触发。当前在~/.bashrc中source的脚本如下:
declare -a ALIASES while read -r; do ALIASES+=("$REPLY") done < <(alias) for i in "${ALIASES[@]}" do ALIAS_AND_NAME=$(awk -F '=' '{print $1}' <<< "$i") # 提取包含alias关键字和别名的部分 NAME_ONLY=$(awk '{print $2}' <<< "$ALIAS_AND_NAME") # 提取别名名称 COMMAND_AFTER_EQUALS=$(sed -e 's/^[^=]*=//g' <<< "$i") # 提取等号后的内容 ALIAS_COMMAND=$(sed -e "s/^'//" -e "s/'$//" <<< "$COMMAND_AFTER_EQUALS") # 移除单引号 # 重新定义别名:先打印别名内容,再执行原命令 alias $NAME_ONLY="echo ~~~alias $NAME_ONLY='$ALIAS_COMMAND'~~~ 1>&2; $ALIAS_COMMAND" done
问题原因
原脚本中,别名里的echo命令默认会读取标准输入(stdin)。当别名参与管道操作时,前序命令的输出会被echo意外接收,导致后续实际命令无法获取到输入。
解决方法
核心思路是让打印别名内容的命令不读取标准输入,有两种简单实现方式:
方式1:重定向echo的标准输入到/dev/null
修改别名定义的最后一行,给echo加上< /dev/null,让它忽略标准输入:
alias $NAME_ONLY="echo ~~~alias $NAME_ONLY='$ALIAS_COMMAND'~~~ 1>&2 < /dev/null; $ALIAS_COMMAND"
方式2:用printf替代echo
printf默认不会读取标准输入,直接替换即可:
alias $NAME_ONLY="printf '~~~alias %s='\''%s'\''~~~\n' '$NAME_ONLY' '$ALIAS_COMMAND' 1>&2; $ALIAS_COMMAND"
两种方式都能保证管道前序命令的输入完整传递给别名对应的实际命令,同时不影响别名内容的打印。
内容的提问来源于stack exchange,提问作者shafe
相关产品推荐
相关产品推荐

