ak0*_*000 8 shell bash shell-script text-processing
我正在寻找一种方法来获取文本文件并将每一行一次一行地放在屏幕上,并具有一定的字符宽度。
有点像简单的幻灯片放映,例如在用户按下键之前查看第一行,然后查看下一行,直到查看完所有行。
我怀疑在 bash 中有一种基本的方法可以做到这一点,但我还没有找到答案。
Ark*_*zyk 12
类似的东西:
#!/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"
Run Code Online (Sandbox Code Playgroud)
命名它centered.sh并像这样使用:
./centered.sh centered.sh
Run Code Online (Sandbox Code Playgroud)
它将打印给定文件中的每一行。按任意键显示下一行。请注意,它尚未经过充分测试,因此请谨慎使用,并且它始终会从屏幕中心开始打印线条,因此会使长线条在底部显示得更多。
第一行:
#!/usr/bin/env bash
Run Code Online (Sandbox Code Playgroud)
是一个shebang。另外,我使用env了其功能。我试图避免使用 Bash 并在 POSIX shell 中编写这个脚本,但我放弃了,因为特别read是非常有问题。您应该记住,尽管 Bash 似乎无处不在,但默认情况下它并不是在所有地方都预设的,例如在 BSD 或带有 Busybox 的小型嵌入式系统上。
在这部分:
if [ ! "$#" -eq 1 ]
then
printf "Usage: %s <file>\n" "$0" >&2
exit 1
fi
Run Code Online (Sandbox Code Playgroud)
我们检查用户是否提供了一个参数,如果没有,我们将使用信息打印到标准错误并返回 1,这意味着父进程出错。
这里
file="$1"
Run Code Online (Sandbox Code Playgroud)
我们将用户传递的文件名参数分配给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"
}
Run Code Online (Sandbox Code Playgroud)
Bash 中没有函数原型,因此您无法提前知道函数需要多少个参数 - 该函数只需要一个参数,即要打印的一行,并使用$1此函数取消引用此函数首先清除屏幕,然后逐行向下移动/ 2 从屏幕顶部到达屏幕中心,然后使用我从这里借用的方法打印居中线。
这是读取用户传递的输入文件并调用display_center()函数的循环
:
while IFS= read -r line
do
display_center "$line"
read -n 1 -s -r </dev/tty
done < "$file"
Run Code Online (Sandbox Code Playgroud)
read使用具有-n 1读取只有一个字符,-s不回射输入来自终端和-r以防止重整反斜杠。您可以了解更多关于read在help read。我们还直接从 /dev/tty 读取,因为 stdin 已经指向该文件 - 如果我们没有告诉read从 /dev/tty 读取,脚本将非常快速地打印文件中的所有行并立即退出,而无需等待用户按一个键。
你可以用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
Run Code Online (Sandbox Code Playgroud)
这是一个基于文本的演示文稿(我认真对待“基本幻灯片”!),不需要 X 会话,一次显示一行。您可以向后或向前移动,它会在最后一行之后结束。