Как повторить тире (дефис) в оболочке
Как я могу повторить символ -
n раз в оболочке? Я прочитал и попробовал этот, но это не работает для -
. Он выдает ошибку invalid option
. Ниже приведена точная команда, которую я использовал:
printf '-%.0s' {1..100}
Исходная строка: printf '-%0.s' {1..100}
Я также попытался выполнить -
, поставив \
, но в этом случае он повторяет \-
n раз.
Ответы
Ответ 1
Это вызывает ошибку:
$ printf '-%.0s' {1..100}; echo ""
bash: printf: -%: invalid option
printf: usage: printf [-v var] format [arguments]
Это работает отлично под bash
:
$ printf -- '-%.0s' {1..100}; echo ""
----------------------------------------------------------------------------------------------------
Для других оболочек попробуйте:
printf -- '-%.0s' $(seq 100); echo ""
Проблема заключалась в том, что printf
ожидает, что -
запускает параметр. Как обычно среди утилит Unix/POSIX в этом типе ситуации, --
сигнализирует printf
, чтобы ожидать больше опций.
Ответ 2
Полезный ответ John1024 предоставляет общее решение, которое показывает, как устранить ошибки из операндов для всех утилит, подобных POSIX.
В данном случае самое простое решение (работает не только в bash
, но и в ksh
и zsh
):
printf '%.0s-' {1..100}
Размещение %.0s
до -
позволяет избежать ошибки ввода начального -
для параметра.
Немного оптимизировано: [1]
printf '%.s-' {1..100}
[1] %.0s
на практике является самой переносимой формой (чтобы быть полностью переносимой, вы также должны избегать расширения скобок {...}
).
%.s
эквивалентная сокращенная форма поддерживается bash
, ksh
и dash
, но не zsh
<= v5.2 - даже если это равно POSIX-совместимый: "Точность [часть после .
] должна иметь форму ('. '), за которым следует десятичная цифра, строка нулевой цифры обрабатывается как ноль."
В качестве бокового примечания: вопрос первоначально содержал доброкачественную (в Bash) опечатку, которая вызвала дебаты: %0.s
вместо %.0s
: %0.s
должен эффективно быть таким же, как %.0s
, и, если на то пошло, то же самое, что и %.s
и %0.0s
(все эффективно запросят: напечатайте поле [минимальной нулевой ширины], заполненное строкой нулевой длины), но на практике это 't: zsh
<= v5.2 не обрабатывает %0.s
правильно (опять же, из-за части .s
).
Аналогично, GNU printf
реализация внешней утилиты (/usr/bin/printf
), как и GNU coreutils v8.24, сообщает об ошибке с %0.s
, поскольку она обычно не принимает ширину поля 0
с s
: invalid conversion specification
- это относится к менее известным оболочкам, которые не предоставляют printf
как встроенный. Обратите внимание, что реализация BSD/OSX не имеет этой проблемы.
Оба поведения zsh
(< = v5.2) с поведением %.s
и GNU /usr/bin/printf
с %0s
являются отклонениями от спецификации POSIX, которые пахнут как ошибки.
Этот вопрос запрашивает поведение zsh
относительно %.s
, и ошибка с тех пор была подтверждена и сообщается как фиксированный через post-v5.2 commit, который еще не выпущен на момент написания этой статьи.
Ответ 3
Используйте цикл for
и диапазон номеров:
for i in {1..10};
do echo "-";
done
Или в одной строке:
for i in {1..10};
do echo -n "-";
done
который выводит ----------
.
EDIT: это было до вашего редактирования printf
.
Ответ 4
Я бы рекомендовал использовать традиционный цикл for
, так как нет необходимости создавать подпроцессы или расширять 100 аргументов:
N=100
for((i = 0; i < $N; ++i)); do
printf -
done
Любопытно, что printf -%s
запускает "недопустимую опцию", но printf -
нет. Возможно, чтобы быть более безопасным, вы могли бы сделать printf %s -
.
Ответ 5
-
jot
может сделать это без багизмов:
jot -s '' -b - 100
-
seq
тоже, но не так, ему нужен tr
:
seq -s- 100 | tr -d '[0-9]'
Ответ 6
Вы также можете использовать tput
вместе с printf
, чтобы выполнить заполнение терминала точным количеством тире, либо напрямую рисовать строку, либо записать строку штрихов в переменную (например, line
) для повторения использование, например чтобы написать строку ширины экрана тире к переменной line
, вы могли бы сделать:
$ eval printf -v line '%.0s-' {1..$(tput cols)}
а затем просто echo "$line"
каждый раз, когда вам нужно нарисовать линию. Вы также можете записать его непосредственно на экран с помощью.
$ eval printf '%.0s-' {1..$(tput cols)}
(Я не большой поклонник eval
, но это одно использование, когда вам гарантировано, что результат команды не может быть вредным).
Ответ 7
Это было моей идеей в течение многих лет... но не для AIX. Изменить последний символ, чтобы изменить повторяющийся символ, который составляет строку
printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' _