Ich suche nach einer Möglichkeit, eine Textdatei zu nehmen und jede Zeile einzeln und mit einer bestimmten Zeichenbreite zentriert auf dem Bildschirm anzuzeigen.
So ähnlich wie eine Diashow mit dem Grundgerüst, bei der der Benutzer beispielsweise die erste Zeile sieht, bis er eine Taste drückt, und dann die nächste Zeile, bis alle Zeilen angezeigt wurden.
Ich vermute, dass es hierfür eine einfache Möglichkeit in Bash gibt, habe aber noch keine Antwort gefunden.
Antwort1
So ähnlich:
#!/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"
Geben Sie ihm einen Namen centered.sh
und verwenden Sie es folgendermaßen:
./centered.sh centered.sh
Es wird jede Zeile aus der angegebenen Datei gedruckt. Drücken Sie eine beliebige Taste, um die nächste Zeile anzuzeigen. Beachten Sie, dass es noch nicht gut getestet ist, also verwenden Sie es mit Vorsicht. Außerdem werden Zeilen immer beginnend in der Bildschirmmitte gedruckt, sodass lange Zeilen weiter unten erscheinen.
Die erste Zeile:
#!/usr/bin/env bash
ist einsiebang. Außerdem verwende ich env
fürseine Eigenschaften. Ich habe versucht, Bash zu vermeiden und dieses Skript in der POSIX-Shell zu schreiben, habe es aber aufgegeben, weil es besonders read
problematisch war. Sie sollten bedenken, dass Bash zwar allgegenwärtig zu sein scheint, aber nicht überall standardmäßig voreingestellt ist, beispielsweise auf BSD oder kleinen eingebetteten Systemen mit Busybox.
In diesem Teil:
if [ ! "$#" -eq 1 ]
then
printf "Usage: %s <file>\n" "$0" >&2
exit 1
fi
Wir prüfen, ob der Benutzer genau einen Parameter angegeben hat. Wenn nicht, drucken wir die Nutzungsinformationen in die Standardfehlerausgabe und geben 1 zurück. Dies bedeutet, dass ein Fehler bei einem übergeordneten Prozess aufgetreten ist.
Hier
file="$1"
Wir weisen den vom Benutzer übergebenen Dateinamenparameter einer Variablen zu,
file
die wir später verwenden werden.
Dies ist eine Funktion, die tatsächlich zentrierten Text druckt:
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"
}
Es gibt keine Funktionsprototypen in Bash, daher können Sie nicht im Voraus wissen, wie viele Parameter die Funktion benötigt - diese benötigt nur einen Parameter, nämlich eine zu druckende Zeile, und diese wird dereferenziert mit $1
Diese Funktion löscht zuerst den Bildschirm, bewegt sich dann vom oberen Bildschirmrand um Zeilen/2 nach unten, um die Bildschirmmitte zu erreichen, und druckt dann eine zentrierte Zeile mit der Methode, die ich von übernommen habeHier.
Dies ist die Schleife, die die vom Benutzer übergebene Eingabedatei liest und
display_center()
die Funktion aufruft:
while IFS= read -r line
do
display_center "$line"
read -n 1 -s -r </dev/tty
done < "$file"
read
wird verwendet, um -n 1
nur ein Zeichen zu lesen, -s
die Eingabe von einem Terminal nicht zu wiederholen und -r
umVerhindern Sie die Verstümmelung von Backslashes. Weitere Informationen finden Sie read
unter help read
. Wir lesen auch direkt von /dev/tty, da stdin bereits auf die Datei verweist. Wenn wir nicht anweisen würden, read
von /dev/tty zu lesen, würde das Skript sehr schnell alle Zeilen aus der Datei drucken und sofort beendet werden, ohne darauf zu warten, dass der Benutzer eine Taste drückt.
Antwort2
Sie können es mit dem Paket tun 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
Es handelt sich um eine textbasierte Präsentation (ich habe „einfache Diashow“ ernst genommen!), die keine X-Sitzung erfordert und bei der immer nur eine Zeile angezeigt wird. Sie können vor- oder zurückblättern und die Präsentation endet nach der letzten Zeile.
Antwort3
Hier ist ein kurzer, schmutziger Einzeiler:
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
Dies setzt ein 80x24-Terminalfenster voraus. Der sed
Befehl zentriert jede Textzeile und fügt dann genügend führende und nachfolgende Zeilenumbrüche hinzu, um sie vertikal zu zentrieren. Der more
Befehl ermöglicht dem Benutzer das Durchblättern.