Ответы:
Обновленный ответ для более общего решения. см. также мой другой ответ ниже, используя только расширение скобки и pritnf.
$ str='Hello World!'
$ sed -r ':loop; s/ (=*):$/\1=:/; t loop' <<< "$(printf '%-20s:\n' "$str" )"
Hello World!========:
Как это устроено?
это (=*):$/захватывает один пробел, один или более =, за которым следует двоеточие :в конце ввода; мы делаем набор =как групповое совпадение и \1будем его обратной ссылкой.
С помощью :loopмы определили названную метку loopи вместе с t loopней перейдем к этой метке, когда a 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 Expansion , оболочка расширяется {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 . так приведут =только s и 20 раз повторились.
Теперь, когда printf '%.20s:\n'мы печатаем только длину 20, $strа если длина $str<20, остальная часть будет =заполняться из сгенерированных s вместо пробелов.