Perintah Linux untuk mengulang string n kali


71

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


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:~$

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}

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}

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

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 :)


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.


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.


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

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

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!


3

Jika Anda menggunakan BSD, Anda bisa menggunakannya seq.

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

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

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.


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'

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"}'


1

Coba yang ini:

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

Akan membuat (seratus dasbor):


Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.