шаблону - bash форматированный вывод




Как я могу повторить символ в bash? (13)

Как я мог сделать это с помощью echo ?

perl -E 'say "=" x 100'

Python вездесущ и работает одинаково везде.

python -c "import sys; print('*' * int(sys.argv[1]))" "=" 100

Символ и счет передаются в виде отдельных параметров.


В bash 3.0 или выше

for i in {1..100};do echo -n =;done

Вот два интересных способа:

[email protected]:~$ yes = | head -10 | paste -s -d '' -
==========
[email protected]:~$ yes = | head -10 | tr -d "\n"
[email protected]:~$ 

Обратите внимание, что эти два метода несколько отличаются. Метод paste заканчивается новой строкой. Метод tr не работает.


Вы можете использовать:

printf '=%.0s' {1..100}

Как это работает:

Bash расширяет {1..100}, поэтому команда становится:

printf '=%.0s' 1 2 3 4 ... 100

Я установил формат printf для =%.0s что означает, что он всегда будет печатать один = независимо от того, какой аргумент он задает. Поэтому он печатает 100 = s.


Как говорили другие, в расширении brah brah предшествует расширение параметра , поэтому диапазоны { m , n } могут содержать только литералы. seq и jot обеспечивают чистые решения, но не полностью переносимы из одной системы в другую, даже если вы используете одну и ту же оболочку для каждого. (Хотя seq становится все более доступным, например, во FreeBSD 9.3 и выше ). eval и другие формы косвенности всегда работают, но несколько неэлегантны.

К счастью, bash поддерживает C-стиль для циклов (только с арифметическими выражениями). Итак, вот краткий «чистый баш»:

repecho() { for ((i=0; i<$1; ++i)); do echo -n "$2"; done; echo; }

Это занимает число повторений в качестве первого аргумента и повторяющуюся строку (которая может быть одним символом, как в описании проблемы) в качестве второго аргумента. repecho 7 b выходы bbbbbbb (завершается символом новой строки).

Деннис Уильямсон дал это решение четыре года назад в своем превосходном ответе на « Создание строки повторяющихся символов в сценарии оболочки» . Мое функциональное тело немного отличается от кода:

  • Поскольку здесь основное внимание уделяется повторению одного символа, а оболочка - bash, вероятно, безопасно использовать echo вместо printf . И я прочитал описание проблемы в этом вопросе как выражение предпочтения печати с echo . Вышеуказанное определение функции работает в bash и ksh93 . Хотя printf более портативен (и обычно должен использоваться для такого рода вещей), синтаксис echo возможно, более читабельен.

    Некоторые встроенные интерпретаторы оболочек интерпретируют сами по себе как опцию - даже при том, что обычный смысл - использовать stdin для ввода, не имеет смысла для echo . zsh делает это. И определенно существуют echo сигналы, которые не распознают -n , поскольку он не является стандартным . (Многие оболочки в стиле Бурна вообще не принимают C-стиль для циклов, поэтому их поведение echo не нужно учитывать ..)

  • Здесь задача состоит в том, чтобы напечатать последовательность; там он должен был назначить его переменной.

Если $n - желаемое количество повторений, и вам не нужно его повторно использовать, и вы хотите что-то еще более короткое:

while ((n--)); do echo -n "$s"; done; echo

n должна быть переменной - этот способ не работает с позиционными параметрами. $s - текст, который нужно повторить.


Нет простого способа. Избегайте циклов с использованием printf и замены.

str=$(printf "%40s")
echo ${str// /rep}
# echoes "rep" 40 times.

Существует несколько способов сделать это.

Использование цикла:

  • Расширение скобки можно использовать с целыми литералами:

    for i in {1..100}; do echo -n =; done    
    
  • C-подобный цикл позволяет использовать переменные:

    start=1
    end=100
    for ((i=$start; i<=$end; i++)); do echo -n =; done
    

Использование встроенного printf :

printf '=%.0s' {1..100}

Указание точности здесь усекает строку, чтобы она соответствовала указанной ширине ( 0 ). Поскольку printf повторно использует строку формата для использования всех аргументов, это просто печатает "=" 100 раз.

Использование head ( printf и т. Д.) И tr :

head -c 100 < /dev/zero | tr '\0' '='
printf %100s | tr " " "="

Чистый путь Bash без eval , никаких подоболочек, никаких внешних инструментов, никаких расширений скобок (т. Е. Число, которое вы можете повторить в переменной):

Если вам задана переменная n которая расширяется до (неотрицательного) числа и переменной pattern , например,

$ n=5
$ pattern=hello
$ printf -v output '%*s' "$n"
$ output=${output// /$pattern}
$ echo "$output"
hellohellohellohellohello

Вы можете сделать это с помощью:

repeat() {
    # $1=number of patterns to repeat
    # $2=pattern
    # $3=output variable name
    local tmp
    printf -v tmp '%*s' "$1"
    printf -v "$3" '%s' "${tmp// /$2}"
}

С этим набором:

$ repeat 5 hello output
$ echo "$output"
hellohellohellohellohello

Для этого небольшого трюка мы используем printf довольно много:

  • -v varname : вместо печати на стандартный вывод printf поместит содержимое форматированной строки в переменную varname .
  • '% * s': printf будет использовать аргумент для печати соответствующего количества пробелов. Например, printf '%*s' 42 будет печатать 42 пробела.
  • Наконец, когда у нас есть требуемое число пробелов в нашей переменной, мы используем расширение параметра для замены всех пространств нашим шаблоном: ${var// /$pattern} будет расширяться до расширения var со всеми замененными пространствами расширение $pattern .

Вы также можете избавиться от переменной tmp в функции repeat , используя косвенное расширение:

repeat() {
    # $1=number of patterns to repeat
    # $2=pattern
    # $3=output variable name
    printf -v "$3" '%*s' "$1"
    printf -v "$3" '%s' "${!3// /$2}"
}

Я предполагаю, что первоначальная цель вопроса состояла в том, чтобы сделать это только с помощью встроенных команд оболочки. Так что for циклов и printf s будет законным, тогда как rep , perl , а также jot ниже не будет. Тем не менее, следующая команда

jot -s "/" -b "\\" $((COLUMNS/2))

например, печатает всю ширину окна \/\/\/\/\/\/\/\/\/\/\/\/


Я только что нашел очень простой способ сделать это, используя seq:

ОБНОВЛЕНИЕ: Это работает на BSD seq который поставляется с OS X. YMMV с другими версиями

seq  -f "#" -s '' 10

Будет напечатан «#» 10 раз, например:

##########
  • -f "#" устанавливает строку формата, чтобы игнорировать числа и просто печатать # для каждого из них.
  • -s '' устанавливает разделитель в пустую строку, чтобы удалить символы новой строки, которые seq вставляет между каждым числом
  • Пространства после -f и -s кажутся важными.

EDIT: здесь это удобная функция ...

repeat () {
    seq  -f $1 -s '' $2; echo
}

Что вы можете назвать так ...

repeat "#" 10

ПРИМЕЧАНИЕ. Если вы повторяете # то цитаты важны!


#!/usr/bin/awk -f
BEGIN {
  OFS = "="
  NF = 100
  print
}

Или

#!/usr/bin/awk -f
BEGIN {
  while (z++ < 100) printf "="
}

Example


for i in {1..100}
do
  echo -n '='
done
echo

repeat() {
    # $1=number of patterns to repeat
    # $2=pattern
    printf -v "TEMP" '%*s' "$1"
    echo ${TEMP// /$2}
}






echo