Ищете способ просматривать строки текстового файла по одной за раз, отцентрировав их на экране?

Ищете способ просматривать строки текстового файла по одной за раз, отцентрировав их на экране?

Я ищу способ взять текстовый файл и поместить каждую строку по одной на экране по центру с определенной шириной символов.

Что-то вроде простого слайд-шоу, например, сначала отображается первая строка, пока пользователь не нажмет клавишу, а затем отображается следующая строка, пока не будут просмотрены все строки.

Подозреваю, что в 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, но я сдался, потому что это 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позволяет пользователю перелистывать страницы.

Связанный контент