Я хотів би вивести 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, щоб заповнити замість пробілів.