คำสั่ง Linux เพื่อทำซ้ำสตริง n ครั้ง


71

มีคำสั่งในตัว Linux ที่อนุญาตให้ส่งออกสตริงที่ n ครั้งสตริงการป้อนข้อมูลหรือไม่


1
โดย "คำสั่ง linux ในตัว" ฉันถือว่าคุณหมายถึงคำสั่งเชลล์และเนื่องจากคุณไม่ได้พูดถึงว่าคุณใช้เชลล์ตัวไหนฉันถือว่ามันใช้งานไม่ได้ คุณสามารถตรวจสอบสิ่งนี้ได้โดยพิมพ์ "echo $ SHELL" ที่บรรทัดคำสั่งและคุณควรได้รับสิ่งที่คล้ายกับ "/ bin / bash" กลับมา หากไม่เป็นเช่นนั้นคุณควรแก้ไขคำตอบเพื่อระบุสิ่งที่จะแสดง ไชโย :)
Adrian Petrescu

7
ฉันติดแท็กคำถามด้วย "bash" ฉันคิดว่าคงเพียงพอแล้ว
GetFree

1
เกี่ยวข้องกับStack Overflow : stackoverflow.com/q/3211891/2157640
Palec

คำตอบ:


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 นั้นไม่ได้ทำอะไรเลยเพียงแค่ไปที่นั่นเพื่อรับข้อโต้แย้ง จากนั้นหากทุบตีได้รับการขัดแย้งมากกว่าที่มีตัวระบุรูปแบบก็จะพิมพ์สำเนาหลายชุดหยิบมากเท่าที่ต้องการ ดังนั้นคุณจะได้รับผลกระทบ ผลลัพธ์ของ "printf 'HelloWorld% d% d \ n' 1 2 3 4 5 6" อาจทำให้ชัดเจนยิ่งขึ้น หวังว่านี่จะช่วยได้!
Adrian Petrescu

ฉันเห็น. มันเป็นพฤติกรรมเฉพาะของ printf สิ่งที่อนุญาตให้ทำซ้ำ
GetFree

1
(ฉันควรทราบว่าจากมุมมองทางทฤษฎีล้วนๆนี่อาจเป็นวิธีที่เร็วที่สุดเนื่องจากมันใช้เชลล์แบบดั้งเดิมเพียงตัวเดียว - ไม่ใช่กระบวนการภายนอกใด ๆ ในความเป็นจริงแม้ว่าเรามาเผชิญหน้ากันประสิทธิภาพของสคริปต์ทุบตีนั้นไม่สำคัญ: )
Adrian Petrescu

1
สิ่งที่เป็นที่เฉพาะเจาะจงเพื่อprintfคือว่ามันซ้ำ ๆ จะนำข้อโต้แย้งเกินสตริงรูปแบบ "บ่วง" ฟรี โดย "ส่วนเกิน" ฉันหมายถึงมีข้อโต้แย้งมากกว่า%ตัวยึดตำแหน่ง
Dennis Williamson

69

นี่เป็นวิธีที่ล้าสมัยที่พกพาสะดวก:

yes "HelloWorld" | head -n 10

นี่คือคำตอบของAdrian Petrescuรุ่นธรรมดาที่ใช้การขยายรั้ง:

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

นั่นเทียบเท่ากับ:

for i in 1 2 3 4 5

นี่เป็นคำตอบของ pike ที่กระชับและมีชีวิตชีวามากกว่านี้เล็กน้อย:

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

คุณจะกำจัดบรรทัดใหม่อย่างไรเมื่อใช้คำสั่ง yes?
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'ซึ่งยังตัดบรรทัดใหม่ขั้นสุดท้าย
Dennis Williamson

2
มันเหมือนกับ Haskell ใน bash shell: Hashell?
wchargin

4
ทางออกที่ใช่ก็ค่อนข้างเรียบร้อย
piggybox

การyesแก้ปัญหาเป็นสิ่งที่ฉันต้องการอย่างแท้จริงเนื่องจากฉันต้องการทำซ้ำคำสั่ง ดังนั้น:yes "$(my-command)" | head -n 2
arnsholt

14

สิ่งนี้สามารถทำให้เป็นพารามิเตอร์ได้และไม่ต้องการตัวแปร temp คือ FWIW:

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

หรือถ้า$Nเป็นขนาดของ bash array:

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

3
นี่คือเวลาที่สั้นที่สุดPOSIX 7วิธีการแก้ปัญหาที่ฉันได้เห็นเพื่อให้ห่างไกลตั้งแต่seq, yesและ{1..5}ไม่ได้ POSIX 7
Ciro Santilli新疆改造中心法轮功六四事件

คุณไม่ควรผสมข้อมูลลงในตัวprintfระบุรูปแบบของ เกิดอะไรขึ้นถ้าข้อมูลมีสตริงรูปแบบ? นี่เป็นวิธีที่ถูกต้องในการระบุ "ความแม่นยำ" (ความยาว) แบบไดนามิก: printf '%*s' "$N"- ทำให้เป็นนิสัยที่จะใส่สตริงรูปแบบในเครื่องหมายคำพูดเดี่ยวเพื่อป้องกันการขยายตัวของตัวแปรที่นั่น
Dennis Williamson

13

ค่อนข้างดีวิธีที่กล่าวถึงแล้ว ไม่สามารถลืมเรื่องอายุที่ดีได้seq:

[john @ awesome] $ สำหรับ i ใน `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:~$ 

เปลือกทุบตีมีพลังมากกว่าที่คนส่วนใหญ่คิด :)


นี่ทำให้ฉันได้รับการโหวตเนื่องจากเป็นระบบภายในทั้งหมด ไม่จำเป็นต้องใช้การฟอร์ก
esm

2
คุณหมายถึงการฟอร์กอะไร? คำตอบเดิมไม่จำเป็นต้องมี เอาต์พุตของ 'type printf' คือ 'printf เป็นเชลล์บิวด์อิน' ดังนั้นจึงรันภายในกระบวนการทุบตีดั้งเดิม
CodeGnome

นี้เป็นเพียงคนเดียวเพื่อให้ห่างไกล ( yes, printf, for i in {1..5}) ที่ถ้าnเป็นศูนย์ก็จะส่งกลับสตริงที่ว่างเปล่าโดยไม่ต้องอยู่สถานะของ 1. นอกจากนี้เนื่องจากการทางคณิตศาสตร์สำหรับการเปรียบเทียบจึงเป็นเรื่องง่ายที่จะมีการชดเชยโดยที่ 1 (เช่นโดยการเปลี่ยน<=ไป<)
Mehrad Mahmoudian

10

คุณสามารถใช้เคล็ดลับ การสะท้อนตัวแปรว่างเปล่าไม่ได้พิมพ์อะไรเลย ดังนั้นคุณสามารถเขียน:

echo word$wojek{1..100}

ถ้า$wojek1 $wojek2... $wojek100เป็นตัวแปรที่ไม่มีอยู่คุณจะได้รับการพูดซ้ำ 100 ครั้งโดยไม่มีสิ่งอื่นใด


1
มันเป็นแฮ็คที่น่าเกลียดและถึงกระนั้นฉันก็อดไม่ได้ที่จะรักและใช้มัน
16807

รักมัน! อาจใช้$_แทน$wojekทำให้เจตนาชัดเจนขึ้น
หมดเวลา Todor

7

ทำซ้ำnครั้งเพียงใส่n-1เครื่องหมายจุลภาคระหว่าง{}:

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

ทำซ้ำ 'helloworld' ซ้ำสองครั้งหลังจากเสียงสะท้อนแรก


5
เยี่ยมมาก แต่ถ้าฉันอยากได้nตัวแปร
GetFree

1
เพิ่มพื้นที่พิเศษหลังจาก 'helloworld'
PADYMKO

ดูเหมือนจะไม่ทำให้คุณใส่ newlines ในสายอักขระอย่างใดอย่างหนึ่ง (เช่นได้รับ helloworld ในบรรทัดของตัวเอง)
TankorSmash


4

ฉันเคยพบคำเตือนไปป์ที่เสียหายกับyesโซลูชันดังนั้นนี่เป็นอีกทางเลือกที่ดี:

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

3

ตามสิ่งที่ pike กำลังพูดถึง

สำหรับอักขระทุกตัวในสตริง echo

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บังคับให้คำสั่งการจัดรูปแบบที่จะนำเสนอ coreutils ของ GNU ถูกใช้เช่นการแจกแจงลินุกซ์และ 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 # Prints "-" 25 ครั้ง
สตีเฟ่น 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

ไม่ใช่ลินุกซ์ในตัว แต่ถ้าคุณติดตั้งไพ ธ อนไว้ ..

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

หรือในหนึ่งบรรทัดตามที่ผู้เสนอความคิดเห็นแนะนำ:

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

4
ไม่เป็นประโยชน์จริง ๆ เพราะมันไม่สามารถรวมเข้ากับเชลล์สคริปต์ได้อย่างง่ายดาย ฯลฯ และเนื่องจากมีวิธีการทำสิ่งนี้ในเปลือกหอยเป็นพันล้านตัวเองฉันเห็นเหตุผลเล็กน้อยที่จะนำปืนขนาดใหญ่ออกมา (เช่น Python) .
Adrian Petrescu

7
ฉันเห็นด้วยกับประเด็นที่สองของคุณ แต่ไม่ใช่หมัด ... มันง่ายที่จะรวมเข้ากับเชลล์สคริปต์: python -c 'พิมพ์ "นี่คือการทดสอบ \ n" * 10'
larsks

ฉันชอบความสามารถในการอ่านของเหตุผลนี้ดีพอสำหรับฉัน ;)
elias


โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.