Команда Linux повторити рядок n разів


71

Чи є вбудована команда Linux, яка дозволяє виводити рядок, що в n разів перевищує рядок введення ??


1
Під "вбудованою командою linux" я припускаю, що ви маєте на увазі команду shell, і оскільки ви не згадуєте, яку оболонку ви використовуєте, я припускаю, що це bash. Ви можете перевірити це, набравши в командному рядку "echo $ SHELL", і ви повинні отримати щось подібне до "/ bin / bash" назад. Якщо ви цього не зробите, вам слід відредагувати свою відповідь, щоб вказати, що вона відображає. Ура :)
Адріан Петреску

7
Я позначив це питання "баш". Я думав, що цього буде достатньо.
GetFree

Відповіді:


75
adrian@Fourier:~$ printf 'HelloWorld\n%.0s' {1..5}
HelloWorld
HelloWorld
HelloWorld
HelloWorld
HelloWorld
adrian@Fourier:~$

3
Чи можете ви пояснити, як це працює? Я розумію команду printf, оскільки вона така сама, як та в C / C ++. Але я не розумію, як розширюється {1..5} і як це працює в поєднанні з частиною "% .0s".
GetFree

4
Це трохи хак :) Спробуйте запустити "printf 'HelloWorld% d \ n' 1 2 3 4 5", і він, ймовірно, натисне для вас. Прапор% .0s покликаний нічого не робити, просто будьте там, щоб взяти аргументи. Тоді, якщо bash отримає більше аргументів, ніж має специфікатори формату, він просто роздрукує кілька копій, захопивши стільки, скільки потрібно. Так ви отримуєте ефект. Вихід "printf 'HelloWorld% d% d \ n' 1 2 3 4 5 6", ймовірно, робить його ще зрозумілішим. Сподіваюся, це допомагає!
Адріан Петреску

Я бачу. Саме поведінка printf дозволяє повторити
GetFree

1
(Слід зазначити, що з суто теоретичної точки зору, це, мабуть, найшвидше рішення, оскільки воно використовує один примітивної оболонки - не будь-які зовнішні процеси. Насправді, погляньмо на це, виконання bash-скриптів насправді не має значення: )
Адріан Петреску

1
Що є специфічним для printfте , що він буде повторно застосувати зайві аргументи в рядок формату, «перекручування» безкоштовно. Під "надлишком" я маю на увазі, що аргументів більше, ніж %заповнювачів.
Денніс Вільямсон

69

Ось старомодний спосіб, який є досить портативним:

yes "HelloWorld" | head -n 10

Це більш звичайна версія відповіді Адріана Петреску з використанням розширення дужок:

for i in {1..5}
do
    echo "HelloWorld"
done

Це еквівалентно:

for i in 1 2 3 4 5

Це трохи більш стисла і динамічна версія відповіді щуки :

printf -v spaces '%*s' 10 ''; printf '%s\n' ${spaces// /ten}

Як позбутися нових рядків, використовуючи команду так?
GetFree

3
Один з способів полягає в трубі це через sed -n 'H;${x;s/\n//gp}'або sed -n ':t;${s/\n//gp};N;bt'інший, щоб зробити echo $(yes "HelloWorld" | head -n 10)що додає пробіл між кожною копії рядка. Ще один спосіб - прокласти його через tr -d '\n'який також виключає остаточний новий рядок.
Денніс Вільямсон

2
Це як Haskell в оболонці: Hashell?
wchargin

4
Рішення так досить акуратне
скарбничка

yesРішення було саме те , що мені було потрібно, так як я хотів , щоб дублювати команду (вихід якого коливається). Таким чином:yes "$(my-command)" | head -n 2
arnsholt

14

Це може бути параметризовано і не вимагає змінної temp, FWIW:

printf "%${N}s" | sed 's/ /blah/g'

Або, якщо $Nрозмір масиву bash:

echo ${ARR[@]/*/blah}

3
Це найкоротше рішення POSIX 7, яке я бачив до цього часу seq, yesі {1..5}це не POSIX 7.
Ciro Santilli 新疆 改造 中心 法轮功 六四 六四

Не слід змішувати дані в printfспецифікатор формату. Що робити, якщо дані містять рядки формату? Це правильний спосіб динамічно вказати "точність" (довжина): printf '%*s' "$N"- зробіть звичку додавати рядок формату в єдині лапки, щоб запобігти розширенню змінної там.
Денніс Вільямсон

13

Чимало вже згадуваних хороших способів. Не можу забути про хороше старе seq:

[john @ awesome] $ for i in `seq 5 '; робити відлуння "Привіт"; зроблено
Привіт
Привіт
Привіт
Привіт
Привіт

Цей насправді поважає нуль, трактуючи його як нуль! ( {i..j}Трюк ніколи не повертає порожній діапазон.)
JellicleCat

10

Можливо, ще один загальний і корисний для вас спосіб:

adrian@Fourier:~$ n=5
adrian@Fourier:~$ for (( c=1; c<=n; c++)) ; do echo "HelloWorld" ; done
HelloWorld
HelloWorld
HelloWorld
HelloWorld
HelloWorld
adrian@Fourier:~$ 

Шкаралупа bash потужніша, ніж думає більшість людей :)


Це отримує мій голос, оскільки він повністю внутрішній; розпалювання не потрібно.
esm

2
На що ви розмовляєте? Оригінальна відповідь не вимагає жодного. Виведенням 'type printf' є 'printf - це вбудована оболонка' і, отже, працює в межах початкового процесу bash.
CodeGnome

Це єдиний до сих пір ( yes, printf, for i in {1..5}) , що якщо nдорівнює нулю, то повертається порожній рядок , не існує стан 1. Також в зв'язку з математичної нотації для порівняння, легко компенсували на 1 (наприклад , шляхом зміни <=в <)
Мехрад Махмудян

10

Можна скористатися хитрістю. Відлуння порожньої змінної нічого не друкує. Тож ви можете написати:

echo word$wojek{1..100}

Якщо $wojek1 $wojek2... $wojek100є неіснуючі змінні, ви повторите своє слово 100 разів без нічого іншого.


1
Це некрасивий некрасивий злом, і все ж я не можу не любити його і використовувати його.
16807

Любіть це! Можливо, використання $_замість цього $wojekробить наміри яснішими.
Михай Тодор

7

Повторіть nрази, просто поставте n-1коми між {}:

$ echo 'helloworld'{,,}
helloworld helloworld helloworld

Повторює "helloworld" двічі після першого відлуння.


5
Приємно, але що робити, якщо я хочу отримати nзмінну?
GetFree

1
це додасть додаткового простору після кожного 'helloworld'
ПАДИМКО

це, мабуть, не дозволяє вам також вводити нові рядки в рядок (тобто отримувати helloworld за власними лініями)
TankorSmash

5
awk 'BEGIN {while (c++<4) printf "Hello"}'

Результат

HelloHelloHelloHello

Використовуйте це без awk: while ((c ++ <5)); робити printf 'привіт'; зроблено
emf

4

У мене виникла помилка з попередженнями про yesвирішення труби , тому ось ще одна хороша альтернатива:

$ seq 4 | sed "c foo"
foo
foo
foo
foo

3

на основі того, на що натякав @pike

для кожного символу в рядку ехо-рядка

echo ${target//?/$replace}

Приклад заголовка, підкресленого =символами

export heading='ABCDEF'; 
export replace='='; 
echo -e "${heading}\n${heading//?/$replace}"

виведе

ABCDEF
======

Це, здається, знаходиться між Linux і OS X, і це робить мене щасливим.

nJoy!


3

Якщо ви перебуваєте на BSD, ви можете просто використовувати seq.

$ seq -f "Hello, world" 5
Hello, world
Hello, world
Hello, world
Hello, world
Hello, world

1
У seq (GNU coreutils) 8.25це дає seq: format 'Hello, world' has no % directive, змушуючи директиву форматування присутнім. Використовуються GNU coreutils, наприклад n багатьох дистрибутивів Linux та Cygwin. Додайте сюди інформацію для тих, хто пропускає інформацію про те, що вона працює лише у послідовності BSD.
Palec

2
line="==========================="
line=${line:0:10}
${line//"="/"ten "}

виходи

ten ten ten ten ten ten ten ten ten ten

Можливо, більш дослідний приклад: оголосити c = '-----'; c = $ {c // $ {c: 0: 1} / $ c}; echo $ c # Друкує "-" 25 разів.
Stephen Niedzielski

2

Якщо припустити, що ви хочете щось подібне до xоператора Perl , де ви автоматично не отримуєте новий рядок між повторами:

x() {
  # usage: x string num
  for i in $(seq 1 $2); do printf "%s" "$1"; done
  # print a newline only if the string does not end in a newline
  [[ "$1" == "${1%$'\n'}" ]] && echo ""
}

x Hi 10  # ==> HiHiHiHiHiHiHiHiHiHi

x $'Hello World!\n' 3

Я явно використовував forцикл, тому що ви не можете писати {1..$n}в bash: розширення дужок робиться перед заміною змінної.


2

Не зовсім вбудований в Linux, але якщо у вас встановлений python ..

python
>>>var = "string"
>>>var*n

Або в одному рядку, як запропонував коментатор:

python -c 'print "This is a test.\n" * 10'

4
Насправді це не так корисно, оскільки його неможливо легко інтегрувати в сценарії оболонки і т. Д. І оскільки існує близько мільярда способів зробити це в самій оболонці, я не бачу причин вивести великі гармати (тобто Python) для цього .
Адріан Петреску

7
Я погоджуюся з вашим другим моментом, але не кулаком ... його легко інтегрувати в сценарій оболонки: python -c 'print "Це тест. \ N" * 10'
larsks

Мені подобається читати це рішення, мені достатньо вагомих причин. ;)
ілій


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.