Я хотів би вивести hello world
більше 20 символів.
printf "%-20s :\n\n" 'hello world!!'
# Actual output
hello world!! :
# Wanted output
hello world!!========:
Однак я не хочу заповнювати пробіли, а замість " = ". Як це зробити?
Я хотів би вивести hello world
більше 20 символів.
printf "%-20s :\n\n" 'hello world!!'
# Actual output
hello world!! :
# Wanted output
hello world!!========:
Однак я не хочу заповнювати пробіли, а замість " = ". Як це зробити?
Відповіді:
Оновлена відповідь для більш загального рішення. дивіться також мою іншу відповідь нижче, використовуючи лише розширення дужки оболонки та pritnf
.
$ str='Hello World!'
$ sed -r ':loop; s/ (=*):$/\1=:/; t loop' <<< "$(printf '%-20s:\n' "$str" )"
Hello World!========:
Як це працює?
це (=*):$/
фіксує один пробіл, один або більше, =
що слідує двокрапкою :
в кінці введення; ми робимо набір =
як груповий матч і \1
будемо його зворотним відсиланням.
З , :loop
ми визначили ярлик з ім'ям loop
і t loop
він буде стрибати на цю мітку , коли s/ (=*):$/\1=:/
зробив успішну заміну;
Заміняючи частину на \1=:
, вона завжди збільшуватиме кількість =
s і повертає саму кишку до кінця рядка.
filler='===================='
string='foo'
printf '%s\n' "$string${filler:${#string}}"
Дає
foo=================
${#string}
- довжина значення $string
і ${filler:${#string}}
є підрядком $filler
від заліку ${#string}
вперед.
Загальна ширина виходу буде максимальною шириною $filler
або $string
.
Рядок наповнювача може jot
бути створений в системах, що мають , динамічно, використовуючи
filler=$( jot -s '' -c 16 '=' '=' )
(для 16 =
у рядку). Системи GNU можуть використовувати seq
:
filler=$( seq -s '=' 1 16 | tr -dc '=' )
Інші системи можуть динамічно використовувати Perl або інший більш швидкий спосіб створення рядка.
printf
для створення фільтра, який є майже у всіх системах, і розширення дужок з оболонками bash/szh
?
printf
+ розширенням дужки bash
?
printf "%.20s:\n\n" "$str========================="
де %.20s
формат обрізання рядків
Один із способів зробити це:
printf "====================:\r%s\n\n" 'hello world!!'
====================\rhello world
, що може бути проблемою, якщо ОП потребує збереження цього, а не просто друку на екрані.
echo -e '=================\rHello World!!'
, але має те саме питання, що і @terdon вказав на це.
echo
підтримки -e
. printf
майже завжди краще, ніж echo
з багатьох причин.
Підхід Perl:
$ perl -le '$k="hello world!!"; while(length($k)<20){$k.="=";} print "$k\n"'
hello world!!=======
Або, краще, @SatoKatsura зазначив у коментарях:
perl -le '$k = "hello world!!"; print $k, "=" x (20-length $k), "\n"'
Якщо вам потрібно підтримати багатобайтові символи UTF, використовуйте:
PERL_UNICODE='AS' perl -le '$k = "hello world!!"; print $k, "=" x (20-length $k), "\n"'
Та сама ідея в оболонці:
v='hello world!!'; while [ ${#v} -lt 20 ]; do v="$v""="; done; printf '%s\n\n' "$v"
perl -le '$k = "hello world!!"; print $k, "=" x (20-length $k), "\n"'
. Однак це (і всі інші рішення, розміщені дотепер), порушується, якщо задіяні багатобайтові символи.
perl6
може бути спосіб зробити це правильно навіть із багатобайтовими символами. Але з іншого боку perl6
дратує так багато способів.
PERL_UNICODE='AS'
. Наприклад: printf '%s' nóóös | perl -nle 'print length($_)'
друкує 8 ("неправильно"), а printf '%s' nóóös | PERL_UNICODE='AS' perl -nle 'print length($_)'
друкує 5 ("правильно").
Інший спосіб - це використовувати лише printf
команду та сгенерувати спочатку візерунок накладки символів Shell Brace Expansion
(Ви можете закінчити числом ≥ область форматування, яку ви хочете надрукувати {1..end}
) та отримати лише кожен перший символ, %.1s
який є =
s, а потім надрукувати лише першу довжину 20 символів область цього %.20s
. Це дещо кращий спосіб повторити символи / слово, а не дублювати їх.
printf '%.20s:\n' "$str$(printf '%.1s' ={1..20})"
Hello World!!=======:
Пояснення:
Зазвичай як розширення Brace , оболонка розширюється {1..20}
наступним чином, якщо ми друкуємо їх.
printf '%s ' {1..20}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
Отже, додавши до нього знак рівності ={1..20}
, оболонка буде розширюватися наступним чином.
printf '%s ' ={1..20}
=1 =2 =3 =4 =5 =6 =7 =8 =9 =10 =11 =12 =13 =14 =15 =16 =17 =18 =19 =20
І printf '%.1s'
що насправді означає printf '%WIDE.LENGTH'
, ми друкуємо лише одну ВЕЛИКУ з вищезгаданих за замовчуванням 1
WIDE . таким чином результат буде =
лише 20 разів повторюватися.
Тепер printf '%.20s:\n'
ми друкуємо лише 20 довжини, $str
а якщо довжина $str
<20, решта займе з генерованих =
s, щоб заповнити замість пробілів.