gpt4 book ai didi

bash - 从脚本中通过管道传输 stdout/stderr 时不显示 read -p 提示

转载 作者:行者123 更新时间:2023-11-29 09:25:35 25 4
gpt4 key购买 nike

我有一个函数旨在捕获命令的输出并缩进每一行:

indent_lines () {
local line
local indent=" "

while IFS= read -r line || [[ -n "$line" ]]; do
# remove \r and replace with \r$indent
echo "$indent $(echo "$line" | sed "s/$(printf '\r')/$(printf '\r')$indent /g")"
done
}

它是这样使用的:

some command 2>&1 | indent_lines

some command 2>&1 的整个输出被输送到 indent_lines 函数中,每一行输出都将被缩进。这适用于从 some command 中调用 read -p 的情况,例如:

get_name () {
echo "this is a line of output 1"
echo "this is a line of output 2"
echo "this is a line of output 3"
read -p "enter your name: " user_input
echo
echo "$user_input is your name"
}

输出是:

$ get_name 2>&1 | indent_lines
$ this is a line of output 1
$ this is a line of output 2
$ this is a line of output 3
$

提示不显示,挂起等待输入。

有什么办法可以让输入暂停前显示提示?

最佳答案

输入端的 while read 循环(与许多其他工具一样)一次处理一行。由于提示未在末尾打印换行符,因此它不会由循环处理。

在高层次上,您有两个选择:

  • 避开提示的管道
  • 添加换行符以便刷新内容

由于 get_name 函数不能被修改是规范的一部分,我们最终要做的是修改 shell 环境以改变 read 的方式有效。


避开管道

read -p 将其提示写入 stderr。

如果要重定向提示,则重定向 FD 2。

如果你想确保其他重定向(例如 2>&1,这会导致提示转到 stdout -- 正在被捕获)不适用,那么直接到TTY 明确:

read -p "enter something" 2>/dev/tty

添加换行符

现在,如果您的目标是运行一个 shell 函数——您不能修改它——通常重定向 stderr,但 read -p 打印提示直接到 TTY,可以通过类似于以下的 hack 来完成:

reading_to_tty() {
read() { builtin read "$@" 2>/dev/tty; }
"$@"
unset -f read
}

...因此:

reading_to_tty get_name 2>&1

...将运行 get_name,使用 read 命令(而不是其他命令)将 stderr 内容直接发送到 TTY。


根据扩展讨论,确保将提示刷新到管道格式的另一种方法是附加换行符。下面是这样做的,因此可以使用通过格式化函数的现有管道:

reading_with_prompt_newline() { 
read() {
if [[ $1 = -p ]]; then
set -- "$1" "$2"$'\n' "${@:3}"
fi
builtin read "$@"
}
"$@"
unset -f read
}

...使用方法同上:

reading_with_prompt_newline get_name 

关于bash - 从脚本中通过管道传输 stdout/stderr 时不显示 read -p 提示,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37445717/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com