![寻找一种在屏幕中心一次查看文本文件行的方法](https://linux22.com/image/169272/%E5%AF%BB%E6%89%BE%E4%B8%80%E7%A7%8D%E5%9C%A8%E5%B1%8F%E5%B9%95%E4%B8%AD%E5%BF%83%E4%B8%80%E6%AC%A1%E6%9F%A5%E7%9C%8B%E6%96%87%E6%9C%AC%E6%96%87%E4%BB%B6%E8%A1%8C%E7%9A%84%E6%96%B9%E6%B3%95.png)
我正在寻找一种方法来获取文本文件并将每一行一次一个地以一定的字符宽度放在屏幕中央。
有点像简单的幻灯片放映,例如,在用户按下某个键之前查看第一行,然后查看下一行,直到查看完所有行。
我怀疑 bash 有一个基本的方法可以做到这一点,但我还没有找到答案。
答案1
像这样的东西:
#!/usr/bin/env bash
if [ ! "$#" -eq 1 ]
then
printf "Usage: %s <file>\n" "$0" >&2
exit 1
fi
file="$1"
display_center(){
clear
columns="$(tput cols)"
lines="$(tput lines)"
down=$((lines / 2))
printf '\n%.0s' $(seq 1 $down)
printf "%*s\n" $(( (${#1} + columns) / 2)) "$1"
}
while IFS= read -r line
do
display_center "$line"
read -n 1 -s -r </dev/tty
done < "$file"
命名它centered.sh
并像这样使用:
./centered.sh centered.sh
它将打印给定文件中的每一行。按任意键显示下一行。请注意,它尚未经过充分测试,因此请谨慎使用,并且它始终会从屏幕中心开始打印行,因此会使长行更多地出现在底部。
第一行:
#!/usr/bin/env bash
是一个舍邦。另外,我env
用它的特点。我尝试避免 Bash 并在 POSIX shell 中编写此脚本,但我放弃了,因为特别read
是问题很大。您应该记住,尽管 Bash 看起来似乎无处不在,但默认情况下它并不是在所有地方都预设的,例如在 BSD 或带有 Busybox 的小型嵌入式系统上。
在这一部分中:
if [ ! "$#" -eq 1 ]
then
printf "Usage: %s <file>\n" "$0" >&2
exit 1
fi
我们检查用户是否提供了一个参数,如果没有,我们将使用信息打印到标准错误并返回 1,这意味着父进程出现错误。
这里
file="$1"
file
我们将用户传递的文件名参数分配给我们稍后将使用的变量 。
这是一个实际打印居中文本的函数:
display_center(){
clear
columns="$(tput cols)"
lines="$(tput lines)"
down=$((lines / 2))
printf '\n%.0s' $(seq 1 $down)
printf "%*s\n" $(( (${#1} + columns) / 2)) "$1"
}
Bash 中没有函数原型,因此您无法提前知道函数需要多少个参数 - 该函数只需要一个参数,即要打印的一行,并且使用该函数取消引用$1
该函数首先清除屏幕,然后向下移动行/ 2 从屏幕顶部到达屏幕中心,然后使用我借用的方法打印中心线这里。
这是读取用户传递的输入文件并调用
display_center()
函数的循环:
while IFS= read -r line
do
display_center "$line"
read -n 1 -s -r </dev/tty
done < "$file"
read
与 一起使用-n 1
仅读取一个字符,-s
不回显来自终端的输入-r
并防止破坏反斜杠。您可以read
在 中了解更多信息help read
。我们还直接从 /dev/tty 读取,因为 stdin 已经指向该文件 - 如果我们没有告诉read
从 /dev/tty 读取,脚本将非常快速地打印文件中的所有行并立即退出,而无需等待用户按一个键。
答案2
你可以用包来做到这一点dialog
:
file=lorem #Path to the file to be displayed
ln=1 #Current line number to be displayed
nlines=$(wc -l "$file"|cut -f1 -d" ") #Total number of lines of file
while [ "$ln" -le "$nlines" ]; do
line=$(sed -n "$ln p" "$file") #sed gets current line
if dialog --yes-label Previous --no-label Next \
--default-button no --yesno "$line" 5 100; then
ln=$((ln-1))
else
ln=$((ln+1))
fi
done
这是一个基于文本的演示文稿(我认真对待“简单的幻灯片放映”!),不需要 X 会话,一次显示一行。您可以向后或向前移动,它会在最后一行之后结束。
答案3
这是一个快速而肮脏的单行:
sed ':a;s/^.\{1,77\}$/ &/;ta;s/\( *\)\1/\1/; s/.*/\n\n\n\n\n\n\n\n\n\n\n&\n\n\n\n\n\n\n\n\n\n\n/' < input.txt | more
这假定终端窗口为 80x24。该sed
命令将每行文本居中,然后添加足够的前导和尾随换行符以垂直居中。该more
命令允许用户翻页。