#bash #format #printf #padding #center
Вопрос:
Я пытаюсь отформатировать вывод с помощью printf, чтобы добиться следующего:
----------------------------------- HEADING -----------------------------------
-------------------------------- LONGER HEADING -------------------------------
Однако мои попытки привели только к:
- HEADING -
- LONGERHEADING -
Мой текущий код выглядит так:
MAGENTA=$(tput setaf 5)
NOCOL=$(tput sgr0)
heading="${1^^}"
width="$(tput cols)"
padlimit=30
if [[ $width -gt 240 ]]; then
padlimit="$(( $width/8 ))"
fi
padding="$(printf '%0.1s' -{1..$padlimit})"
printf '%s%*.*s %s %*.*s%sn' "$MAGENTA" 0 "$(((width-2-${#heading})/2))" "$padding"
"$heading" 0 "$(((width-2-${#heading})/2))" "$padding" "$NOCOL"
Если я попытаюсь жестко padding
закодировать элемент счетчика переменной, например так:
MAGENTA=$(tput setaf 5)
NOCOL=$(tput sgr0)
heading="${1^^}"
width="$(tput cols)"
padding="$(printf '%0.1s' -{1..60})"
printf '%s%*.*s %s %*.*s%sn' "$MAGENTA" 0 "$(((width-2-${#heading})/2))" "$padding"
"$heading" 0 "$(((width-2-${#heading})/2))" "$padding" "$NOCOL"
Результаты таковы:
------------------------------ HEADING ------------------------------
------------------------------ LONGER HEADING ------------------------------
Я полагаю, что математика в этом printf
утверждении неверна. Однако я не уверен в том, что:
- Какова
printf
должна быть арифметика в заявлении; и - Почему при предоставлении
padding
переменной элементу count переменной она не вычисляется?
Любая помощь будет оценена по достоинству!
Комментарии:
1. Вопросительный взгляд на ваш сценарий, это приведет к сбою
printf '%0.1s' -{1..$padlimit}
, потому что расширение переменной происходит до того, как расширение фигурных скобок, поbash
крайней мере, вставит ваш сценарий в shellcheck.net для подтверждения/рекомендации.2. Не существует простого способа повторить символ или строку определенное количество раз с
printf
помощью команды или функции C. Это затрудняет создание длинной очереди. В Perl естьx
оператор:perl -e 'print "-" x 32, "n"'
печатает 32 тире. Другие языки сценариев имеют аналогичный синтаксис. AFAIK,printf
команда не поддерживает никаких аналогичных/эквивалентных обозначений.3. Ваши выходные данные показывают разную длину строк, поэтому вы, вероятно, не учитываете длину ваших строк. т. е.
width/2 - length(header) / 2 - 1
длину префиксных и постфиксных тире. Затем вы печатаете пробел и заголовок между ними.4. То, что вы пытаетесь сделать, бесполезно, потому что в настоящее время терминалы не имеют фиксированной ширины. Всякий раз, когда вы меняете размер окна терминала, макет, который вы пытаетесь создать, портится. Ансибль похож на глупость, и всякий раз, когда я его использую, он меня раздражает.
Ответ №1:
Просто напишите цикл for и распечатайте -
в цикле for.
center() {
local heading width headinglen padlength i
heading="$*"
width="$(tput cols)"
headinglen=${#heading}
padlength=$(( (width - 2 - headinglen) / 2 ))
for ((i = 0; i < padlength; i)); do
printf "-"
done
printf " %s " "$heading"
for ((i = 0; i < padlength; i)); do
printf "-"
done
if (( (width - 2 - headinglen) % 2 )); then
printf "-"
fi
printf "n"
}
center HEADING
center LONGER HEADING
Ответ №2:
Как указывалось в комментариях Jetchisel и Джонатана Леффлера, проблемы с вашим исходным кодом заключались в том, что расширение скобок не будет работать с переменной внутри и, следовательно printf
, само по себе не может делать то, что вы хотите.
Чистым решением bash было бы использование цикла, и это устранило бы необходимость в полях ширины в команде printf:
MAGENTA=$(tput setaf 5)
NOCOL=$(tput sgr0)
heading="${1^^}"
width="$(tput cols)"
padlength=$(((width-2-${#heading})/2))
padding=""
i=0
while [[ $i -lt $padlength ]]; do
padding ='-'
((i ))
done
printf '%s%s %s %s%sn' "$MAGENTA" "$padding" "$heading" "$padding" "$NOCOL"
Ограничение pad в вашем исходном коде часто нарушало единообразие длин строк в моих (небольших) окнах эмулятора терминала, но вот как вы бы реализовали его с помощью цикла:
MAGENTA=$(tput setaf 5)
NOCOL=$(tput sgr0)
heading="${1^^}"
width="$(tput cols)"
padlimit=30
if [[ $width -gt 240 ]]; then
padlimit="$(( $width/8 ))"
fi
padlength=$(((width-2-${#heading})/2))
padding=""
i=0
while [[ $i -lt $padlength amp;amp; $i -lt $padlimit ]]; do
padding ='-'
((i ))
done
printf '%s%s %s %s%sn' "$MAGENTA" "$padding" "$heading" "$padding" "$NOCOL"