Bir dizeyi n kere tekrarlamak için Linux komutu


71

Bir giriş dizesinin n katı olan bir dizgenin çıktısını almayı sağlayan herhangi bir yerleşik Linux komutu var mı?


1
"Yerleşik linux komutu" ile, kabuk komutunu kastediyorsunuz ve hangi kabuğu kullandığınızdan bahsetmediğiniz için bash olduğunu varsayıyorum. Bunu komut satırına "echo $ SHELL" yazarak kontrol edebilirsiniz ve geri "/ bin / bash" komutuna benzer bir şey almalısınız. Yapmazsanız, ne göstereceğini belirtmek için cevabınızı düzenlemelisiniz. Şerefe :)
Adrian Petrescu

7
Soruyu "bash" ile etiketledim. Bunun yeterli olacağını düşünmüştüm.
GetFree

Yanıtlar:


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

3
Bunun nasıl çalıştığını açıklayabilir misiniz? Printf komutunu anlıyorum çünkü C / C ++ ile aynı. Fakat {1..5} 'in nasıl genişletildiğini ve bunun "% .0s" kısmı ile birlikte nasıl çalıştığını anlamıyorum.
GetFree

4
Biraz kesmek :) :) "printf 'HelloWorld% d \ n' 1 2 3 4 5" çalıştırmayı deneyin ve muhtemelen sizin için tıklayacaktır. % .0s bayrağı hiçbir şey yapmamak içindir, sadece argümanları almak için orada olun. Ardından, bash, format belirticilere göre daha fazla argüman alırsa, gerektiği kadar kaparak basitçe birden fazla kopya basar. Yani etkiyi görüyorsun. "Printf 'HelloWorld% d% d \ n' 1 2 3 4 5 6" çıktısı muhtemelen daha da netleşiyor. Bu yardımcı olur umarım!
Adrian Petrescu

Anlıyorum.
Printf'in

1
(Tamamen teorik bir bakış açısından bakıldığında, bunun en hızlı çözüm olduğuna dikkat etmeliyim çünkü tek bir kabuk ilkel kullanıyor - herhangi bir dış süreç değil. Gerçekte, bununla birlikte, bash scriptlerinin performansı gerçekten önemli değil: )
Adrian Petrescu

1
Ne olduğunu özgü printfdefalarca ücretsiz biçim dizesi, "döngü" aşırı argümanlar uygulanacak olmasıdır. "Aşırı" derken, %yer tutuculardan daha fazla argüman olduğunu kastediyorum .
Dennis Williamson,

69

İşte oldukça taşınabilir bir eski moda yolu:

yes "HelloWorld" | head -n 10

Bu, Adrian Petrescu'nun ayraç genişlemesini kullanarak yanıtının daha geleneksel bir sürümüdür :

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

Bu eşdeğerdir:

for i in 1 2 3 4 5

Bu, pike'nin cevabının biraz daha özlü ve dinamik bir versiyonudur :

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

Yes komutunu kullanırken yeni satırlardan nasıl kurtulursunuz?
GetFree

3
Bunun bir yolu, onu sed -n 'H;${x;s/\n//gp}'veya sed -n ':t;${s/\n//gp};N;bt'diğerlerini yönlendirmek, echo $(yes "HelloWorld" | head -n 10)dize her kopyası arasına bir boşluk ekleyen yapmaktır . Diğer bir yol da, boru tr -d '\n'hattını son boru hattını ortadan kaldıran boru hattıdır.
Dennis Williamson,

2
Bir bash kabuğundaki Haskell gibi: Hashell?
wchargin

4
Evet çözümü oldukça temiz
piggybox

yesBen (kimin çıktı dalgalandığı) bir komut çoğaltmak istedik çünkü çözüm, tam olarak ne ihtiyaç vardı. Böylece:yes "$(my-command)" | head -n 2
arnsholt 14

14

Bu parametrelendirilebilir ve geçici bir değişken gerektirmez, FWIW:

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

Veya $Nbir bash dizisinin büyüklüğü ise:

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

3
Bu kısa olduğu POSIX 7 şimdiye kadar kaçak gördüğüm çözüm seq, yesve {1..5}7. POSIX değildir
Ciro Santilli新疆改造中心法轮功六四事件

Verileri printfformat belirticisine karıştırmamalısınız . Veriler format dizeleri içeriyorsa ne olur? Bu, "hassaslığı" (uzunluk) dinamik olarak belirtmenin doğru yoludur: printf '%*s' "$N"- değişken genişlemeyi önlemek için format dizesini tek tırnak içine almayı alışkanlık haline getirin.
Dennis Williamson,

13

Bahsedilen birkaç iyi yol. Eski güzel hakkında unutamam seq:

[john @ awesome] $ 'i 5 seklinde; yankı yapmak "Merhaba"; bitti
Selam
Selam
Selam
Selam
Selam

Bu gerçekten de sıfıra saygı duyuyor, sıfıra bakıyor! ( {i..j}
Püf noktası

10

Belki de sizin için daha genel ve kullanışlı başka bir yol:

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

Beşinci kabuk, çoğu insanın düşündüğünden daha güçlüdür :)


Bu tamamen oyuna dahil olduğu için oyumu alıyor; çatal gerekmez.
esm

2
Hangi çataldan bahsediyorsun? Orijinal cevap hiçbiri gerektirmez. 'Printf' türünün çıktısı 'printf yerleşik bir kabuktur' ve bu nedenle orijinal bash işlemi içinde çalışır.
CodeGnome

Bu şimdiye kadar (tek yes, printf, for i in {1..5}) eğer nsıfır, boş dize döndürür nedeniyle karşılaştırma için matematiksel gösterime Ayrıca 1. durumunu mevcut olmadan, 1 telafi etmiş kolaydır (değiştirerek örneğin <=etmek <)
Mehrad Mahmoudian

10

Bir numara kullanabilirsiniz. Boş bir değişkeni tekrarlamak hiçbir şey yazdırmaz. Böylece yazabilirsiniz:

echo word$wojek{1..100}

Eğer $wojek1 $wojek2... $wojek100mevcut olmayan değişkenler ise, sözünüzü başka bir şey olmadan 100 kez tekrar ettireceksiniz.


1
Bu çirkin bir kesmek, ama yine de yardım edemem ama onu sevip kullanıyorum.
16807,

Sevdim! Belki de $_yerine kullanmak $wojekniyetini daha net gösterir.
Mihai Todor

7

Tekrarla n, sadece n-1aralarına virgül koy {}:

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

İlk yankıdan sonra 'helloworld' i iki kez tekrarlar.


5
Güzel, peki ya nbir değişkenden almak istersem ?
GetFree

1
her 'helloworld'den sonra fazladan bir boşluk
katar

bu, dizgede yeni satırlar koymanıza izin vermiyor gibi görünüyor (yani helloworld'ü kendi satırlarında alma)
TankorSmash,

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

Sonuç

Merhaba Merhaba Merhaba Merhaba

Bunu awk olmadan kullanın: while ((c ++ <5)); printf 'merhaba'; bitmiş
emf

4

Çözümle birlikte kırılmış boru uyarıları yaşadım yes, işte bir başka güzel alternatif:

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

3

@pike'ın ima ettiği şeye dayanarak

string echo string'deki her karakter için

echo ${target//?/$replace}

=Karakterlerle altı çizili başlık örneği

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

çıkacak

ABCDEF
======

Bu Linux ve OS X arasındaki bağlantı gibi görünüyor ve bu beni mutlu ediyor.

Njoy!


3

BSD kullanıyorsanız, sadece kullanabilirsiniz seq.

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

1
İçinde seq (GNU coreutils) 8.25, bu seq: format 'Hello, world' has no % directive, bir formatlama direktifinin varlığını zorlayarak verir . GNU coreutils, örneğin birçok Linux dağıtımında ve Cygwin'de kullanılır. Buradaki bilgileri yalnızca BSD seq.
Palec

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

çıktılar

ten ten ten ten ten ten ten ten ten ten

Belki daha ayrıntılı bir örnek: declare c = '-----'; C = $ {c // $ {C: 0: 1} / $ c}; echo $ c # "-" basımını 25 kez yapar.
Stephen Niedzielski

2

Perl'in xoperatörü gibi bir şey istediğinizi varsayalım , burada tekrarlamalar arasında otomatik olarak yeni bir satır alamazsınız:

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

Açıkça bir fordöngü kullandım çünkü {1..$n}bash yazamıyorsunuz : ayraç genişletme değişken değiştirmeden önce yapılır.


2

Tam olarak Linux'ta yerleşik değil, eğer yüklü python varsa ..

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

Ya da bir satırda, yorumcunun önerdiği gibi:

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

4
Bu o kadar da kullanışlı değil, kabuk senaryolarına kolayca entegre edilemediğinden, vb. Bunu kabuğun kendisinde yapmanın milyarlarca yolu olduğundan, bunun için büyük silahları (yani Python) ortaya çıkarmak için çok az neden görüyorum. .
Adrian Petrescu

7
İkinci noktanla aynı fikirdeyim ama yumruk değil ... bir kabuk betiğine entegre etmek kolaydır: python -c 'print "Bu bir testtir. \ N" * 10'
larsks

Bu çözümün okunabilirliğini seviyorum, benim için yeterli bir neden. ;)
elias

2

Burada sihir yok:

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


1

Bunu dene:

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

Yaratacağım (yüz tire):


Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.