Perintah Linux untuk mengulang string n kali

71

Apakah ada perintah built-in Linux yang memungkinkan untuk mengeluarkan string yang n kali input string ??

Mendapatkan gratis
sumber
1
Dengan "built-in linux command" Saya berasumsi maksud Anda perintah shell, dan karena Anda tidak menyebutkan shell yang Anda gunakan, saya menganggap itu bash. Anda dapat memeriksa ini dengan mengetikkan "echo $ SHELL" di baris perintah dan Anda akan mendapatkan sesuatu yang mirip dengan "/ bin / bash" kembali. Jika tidak, Anda harus mengedit jawaban untuk menentukan apa yang ditampilkan. Cheers :)
Adrian Petrescu
7
Saya menandai pertanyaan dengan "bash". Saya pikir itu sudah cukup.
GetFree

Jawaban:

75
adrian@Fourier:~$ printf 'HelloWorld\n%.0s' {1..5}
HelloWorld
HelloWorld
HelloWorld
HelloWorld
HelloWorld
adrian@Fourier:~$
Adrian Petrescu
sumber
3
Bisakah Anda menjelaskan cara kerjanya? Saya mengerti perintah printf karena sama dengan yang ada di C / C ++. Tapi saya tidak mengerti bagaimana {1..5} diperluas dan bagaimana itu bekerja bersama dengan bagian "% .0s".
GetFree
4
Ini sedikit hack :) Coba jalankan "printf 'HelloWorld% d \ n' 1 2 3 4 5" dan mungkin akan klik untuk Anda. Bendera% .0s dimaksudkan untuk tidak melakukan apa-apa, hanya ada di sana untuk mengambil argumen. Kemudian, jika bash mendapatkan lebih banyak argumen daripada yang memiliki format penentu, itu hanya akan mencetak banyak salinan, meraih sebanyak yang dibutuhkan. Jadi, Anda mendapatkan efeknya. Output dari "printf 'HelloWorld% d% d \ n' 1 2 3 4 5 6" mungkin membuatnya lebih jelas. Semoga ini membantu!
Adrian Petrescu
Saya melihat. Ini adalah perilaku khusus dari printf yang memungkinkan pengulangan
GetFree
1
(Saya harus mencatat bahwa, dari sudut pandang teoretis murni, ini mungkin solusi tercepat karena menggunakan primitif shell tunggal - bukan proses eksternal. Pada kenyataannya, mari kita hadapi itu, kinerja skrip bash tidak terlalu penting: )
Adrian Petrescu
1
Apa adalah khusus untuk printfadalah bahwa hal itu berulang kali akan berlaku argumen kelebihan untuk format string, "looping" gratis. Dengan "kelebihan", maksud saya ada lebih banyak argumen daripada %placeholder.
Dennis Williamson
69

Berikut cara kuno yang cukup portabel:

yes "HelloWorld" | head -n 10

Ini adalah versi yang lebih konvensional dari jawaban Adrian Petrescu menggunakan brace expansion:

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

Itu setara dengan:

for i in 1 2 3 4 5

Ini adalah versi jawaban pike yang lebih ringkas dan dinamis :

printf -v spaces '%*s' 10 ''; printf '%s\n' ${spaces// /ten}
Dennis Williamson
sumber
Bagaimana Anda menyingkirkan baris baru saat menggunakan perintah ya?
GetFree
3
Salah satu caranya adalah menyalurkannya melalui sed -n 'H;${x;s/\n//gp}'atau yang sed -n ':t;${s/\n//gp};N;bt'lain adalah dengan melakukan echo $(yes "HelloWorld" | head -n 10)yang menambah ruang antara setiap salinan string. Namun cara lain adalah menyalurkan melalui tr -d '\n'yang juga menghilangkan baris baru akhir.
Dennis Williamson
2
Ini seperti Haskell dalam bash shell: Hashell?
wchargin
4
Solusi ya cukup rapi
piggybox
The yessolusi adalah apa yang saya butuhkan, karena aku ingin menduplikasi perintah (yang output berfluktuasi). Jadi:yes "$(my-command)" | head -n 2
arnsholt
14

Ini dapat parameter dan tidak memerlukan variabel temp, FWIW:

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

Atau, jika $Nukuran array bash:

echo ${ARR[@]/*/blah}
twifkak
sumber
3
Ini adalah solusi POSIX 7 terpendek yang telah saya lihat sejauh ini seq, yesdan {1..5}bukan POSIX 7.
Ciro Santilli 新疆 改造 中心 法轮功 六四 事件
Anda tidak boleh mencampur data ke dalam printfpenentu format. Bagaimana jika data berisi string format? Ini adalah cara yang benar untuk secara dinamis menentukan "presisi" (panjang): printf '%*s' "$N"- biasakan untuk melampirkan string format dalam tanda kutip tunggal untuk mencegah ekspansi variabel di sana.
Dennis Williamson
13

Cukup banyak cara bagus yang telah disebutkan. Tidak bisa melupakan tua yang baik seq:

[john @ mengagumkan] $ untuk saya di `seq 5`; lakukan gema "Hai"; selesai
Hai
Hai
Hai
Hai
Hai
John T
sumber
Yang ini benar-benar menghargai nol, memperlakukannya nol! ( {i..j}Triknya tidak pernah mengembalikan rentang kosong.)
JellicleCat
10

Mungkin cara lain yang lebih umum dan bermanfaat bagi Anda:

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

Shell bash lebih kuat dari yang dipikirkan kebanyakan orang :)

Adrian Petrescu
sumber
Ini mendapatkan suara saya, karena sepenuhnya shell-internal; tidak perlu forking.
esm
2
Forking apa yang Anda maksud? Jawaban aslinya tidak memerlukan apa pun. Output dari 'type printf' adalah 'printf adalah shell builtin' dan karenanya berjalan dalam proses bash asli.
CodeGnome
Ini adalah satu-satunya sejauh ( yes, printf, for i in {1..5}) bahwa jika nadalah nol, ia mengembalikan string kosong tanpa ada status 1. Juga karena notasi matematika untuk perbandingan, mudah telah diimbangi dengan 1 (misalnya dengan mengubah <=ke <)
Mehrad Mahmoudian
10

Anda bisa menggunakan trik. Menggema variabel kosong tidak akan mencetak apa pun. Jadi, Anda dapat menulis:

echo word$wojek{1..100}

Jika $wojek1 $wojek2... $wojek100adalah variabel yang tidak ada, Anda akan mengulangi kata-kata Anda 100 kali tanpa hal lain.

Wojciech Waga
sumber
1
Ini adalah retas buruk rupa, namun saya tidak bisa tidak menyukainya dan menggunakannya.
16807
Suka! Mungkin menggunakan $_bukannya $wojekmemperjelas niat.
Mihai Todor
7

Ulangi nkali, cukup beri n-1koma di antara {}:

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

Ulangi 'helloworld' dua kali setelah gema pertama.

kev
sumber
5
Bagus, tetapi bagaimana jika saya ingin dapatkan ndari variabel?
GetFree
1
itu menambah ruang ekstra setelah setiap 'helloworld'
PADYMKO
ini sepertinya tidak membiarkan Anda memasukkan baris baru dalam string (mis. mendapatkan helloworld di jalur mereka sendiri)
TankorSmash
5
awk 'BEGIN {while (c++<4) printf "Hello"}'

Hasil

Halo halo halo halo
Steven Penny
sumber
Gunakan ini tanpa awk: while ((c ++ <5)); jangan printf 'halo'; selesai
emf
4

Saya telah mengalami peringatan pipa yang rusak dengan yessolusinya, jadi inilah alternatif lain yang bagus:

$ seq 4 | sed "c foo"
foo
foo
foo
foo
n.caillou
sumber
3

berdasarkan apa yang @pike isyaratkan

untuk setiap karakter dalam string gema string

echo ${target//?/$replace}

Contoh tajuk yang digarisbawahi dengan =karakter

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

akan menampilkan

ABCDEF
======

Ini sepertinya port antara linux dan OS X dan itu membuat saya senang.

nJoy!

nickl-
sumber
3

Jika Anda menggunakan BSD, Anda bisa menggunakannya seq.

$ seq -f "Hello, world" 5
Hello, world
Hello, world
Hello, world
Hello, world
Hello, world
Qix
sumber
1
Dalam seq (GNU coreutils) 8.25, ini memberi seq: format 'Hello, world' has no % directive, memaksa arahan pemformatan untuk hadir. GNU coreutils digunakan misalnya pada banyak distribusi Linux dan Cygwin. Termasuk info di sini untuk mereka yang kehilangan info bahwa itu hanya berfungsi di BSD seq.
Palec
2
line="==========================="
line=${line:0:10}
${line//"="/"ten "}

output

ten ten ten ten ten ten ten ten ten ten
commonpike
sumber
Mungkin contoh yang lebih bertele-tele: menyatakan c = '-----'; c = $ {c // $ {c: 0: 1} / $ c}; echo $ c # Cetakan "-" 25 kali.
Stephen Niedzielski
2

Dengan asumsi Anda menginginkan sesuatu seperti xoperator Perl , di mana Anda tidak secara otomatis mendapatkan baris baru di antara pengulangan:

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

Saya secara eksplisit menggunakan forloop karena Anda tidak dapat menulis {1..$n}di bash: ekspansi brace dilakukan sebelum substitusi variabel.

glenn jackman
sumber
2

Tidak persis built in ke linux, tetapi jika Anda memiliki python diinstal ..

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

Atau dalam satu baris, seperti yang disarankan komentator:

python -c 'print "This is a test.\n" * 10'
eqzx
sumber
4
Tidak terlalu berguna, karena tidak dapat dengan mudah diintegrasikan ke dalam skrip shell, dll. Dan karena ada sekitar satu miliar cara untuk melakukan ini dalam shell itu sendiri, saya melihat sedikit alasan untuk mengeluarkan senjata besar (yaitu Python) untuk itu .
Adrian Petrescu
7
Saya setuju dengan poin kedua Anda tetapi bukan kepalan tangan ... mudah untuk diintegrasikan ke dalam skrip shell: python -c 'print "Ini adalah ujian. \ N" * 10'
larsks
Saya suka keterbacaan solusi ini, alasan yang cukup bagi saya. ;)
elias
2

Tidak ada keajaiban di sini:

seq 5 | awk '{print "Hello World"}'

brablc
sumber
1

Coba yang ini:

echo $(for i in $(seq 1 100); do printf "-"; done)

Akan membuat (seratus dasbor):


Alle Aldine
sumber