提问人:Calisthenics 提问时间:7/6/2023 更新时间:7/6/2023 访问量:67
Bash 从循环输出文本格式
Bash output text formatting from loop
问:
我只是想从我运行的单行脚本中清理一些输出,以检查文件是否存在。为了测试,我使用在同一目录上打开的 2 个不同的终端并运行一个连续的“while true 循环”来检查文件是否存在,以及 if 语句有条件地输出消息,同时让另一个终端生成并删除测试文件用于测试。
航站楼-1dir: $ rm file ; sleep 10 ; touch file
航站楼-2dir: $ while true ; do if [[ -e $file ]] ; then echo -e "\e[1;32m FILE EXISTS\e[0m" ; break ; else echo -en "\e[1;31m FILE DOES NOT EXIST YET\e[0m\r" ; fi ; done
最终发生的事情是,我在 else 条件下获得了我想要的输出,因为“FILE DOES NOT EXIST”,但是当“”消息出现时,它会覆盖第一个但仅覆盖字符串的长度,所以我会得到”FILE EXISTS
FILE EXISTSOT EXIST
"
ChatGPT一直无济于事。有人有什么提示吗?我正在使用第二个回声,并将其全部保持在一行上,并可作为输出到终端进行管理,直到我收到我的 FILE EXISTS 消息。我希望它在同一条线上都干净,并且在第一个回声上使用相同的回声无济于事。-n
\r
-n
\r
答:
您永远不会擦除该行,因此,如果您在较长的文本上写较短的文本,则部分旧文本将保持可见。
你可以做一个
tput el
(el
= 从光标清除到行尾)在打印新文本之前。
使用代替,因为前者是标准的,而不是后者。printf
echo -en
#!/usr/bin/env sh
file=$1
while :; do
if [ -e "$file" ]; then
printf '\e[1;32mFILE EXISTS\e[0m\e[K\n'
break
else
sleep .2
printf '\e[1;31mFILE DOES NOT EXIST YET\e[0m\r'
fi
done
此外,使用可能是监视文件创建事件的更明智的选择。inotifywait
在那里,循环只针对每个创建事件运行,因此不会忙于加载 CPU 探测文件以实现。
#!/usr/bin/env sh
filePath=$1
baseDir=${filePath%/*}
[ "$baseDir" = "$filePath" ] && baseDir=./
while
! [ -e "$filePath" ] &&
printf '\r\e[1;31mFILE DOES NOT EXIST YET\e[0m'
do
inotifywait -qqe create "$baseDir"
done
printf '\r\e[1;32mFILE EXISTS\e[0m\e[K\n'
评论
\e[K
printf '\e[1;32mFILE EXISTS\e[0m\e[K\n'
inotifywait
最简单的方法是使用:
printf "\r\e[K\e[1;32m%-*s\e[0m\n" "${COLUMNS}" 'FILE EXIST'
因此,结合起来,这将创建以下脚本:
printf '\e[1;31mFILE DOES NOT EXIST YET\e[0m'
while ! [ -e "$file" ]: do sleep 1; done
printf "\r\e[K\e[1;32m%-*s\e[0m\n" "${COLUMNS}" 'FILE EXIST'
在这里,我们避免连续写同一行
注意;请注意,它不会删除一行,它只是执行 carage 返回。如果将输出重定向到文件,原始数据仍将存在。\r
详细信息在这里: 有没有比回声 “ ” 更好的擦除线条的方法?
评论
FILE EXISTS
\e[2K
while true; do if [[ -e $file ]]; ... break;
while ! [[ -e $file ]]; do ...
\e[K
\e[0m