คำสั่งนั้นขึ้นอยู่กับเชลล์ที่สร้างอาร์กิวเมนต์จำนวน 5,000 ข้อและส่งต่อไปยังprintf
สิ่งที่ไม่สนใจ ในขณะที่มันอาจดูค่อนข้างเร็ว - และสัมพันธ์กับบางสิ่ง - เชลล์จะต้องสร้างสตริงเหล่านั้นทั้งหมดเป็น args (และกำหนดขอบเขต)และอื่น ๆ
นอกเหนือจากข้อเท็จจริงที่ว่า Hs ที่สร้างขึ้นไม่สามารถพิมพ์ได้จนกว่าเชลล์จะทำซ้ำถึง 5,000 ครั้งแรกคำสั่งนั้นจะมีค่าใช้จ่ายในหน่วยความจำทั้งหมดที่ใช้ในการจัดเก็บและกำหนดขอบเขตอาร์กิวเมนต์สตริงตัวเลขให้เป็นprintf
บวกกับ Hs เช่นเดียวกับที่คุณสามารถทำได้:
printf %05000s|tr \ H
... ซึ่งสร้างสตริงของช่องว่าง 5000 - ซึ่งอย่างน้อยที่สุดจะมีเพียงไบต์เดียวต่อหนึ่งและไม่มีค่าใช้จ่ายใด ๆ ในการกำหนดเขตเนื่องจากไม่มีการคั่น การทดสอบบางอย่างบ่งชี้ว่าแม้กระทั่งน้อยถึง 5,000 ไบต์ค่าใช้จ่ายของทางแยกและท่อที่จำเป็นสำหรับการtr
มีค่ามันแม้ในกรณีนี้และมันเกือบจะทุกครั้งคือเมื่อตัวเลขสูงขึ้น
ฉันวิ่ง ...
time bash -c 'printf H%.0s {1..5000}' >/dev/null
...และ...
time bash -c 'printf %05000s|tr \ H' >/dev/null
แต่ละชิ้นมีความยาวประมาณ 5 เท่า(ไม่มีข้อมูลเชิงวิทยาศาสตร์ที่นี่ - เพียงอย่างเดียวเท่านั้น)และรุ่นส่วนขยายรั้งเฉลี่ยน้อยกว่า 0.02 วินาทีในเวลาประมวลผลทั้งหมด แต่tr
รุ่นมาโดยเฉลี่ยประมาณ 0.12 วินาที - และtr
รุ่นเอาชนะได้ ทุกเวลา. ฉันไม่สามารถบอกได้ว่าฉันประหลาดใจ - {brace expansion}
เป็นคุณสมบัติชวเลขเชลล์แบบโต้ตอบที่มีประโยชน์ แต่มักจะเป็นสิ่งที่ค่อนข้างสิ้นเปลืองในการทำสิ่งที่เกี่ยวข้องกับการเขียนสคริปต์ รูปแบบทั่วไป:
for i in {[num]..[num]}; do ...
... เมื่อคุณคิดเกี่ยวกับมันเป็นสอง for
ลูป - อย่างแรกคือภายในและส่อให้เห็นว่าเชลล์ต้องวนในบางวิธีเพื่อสร้างตัววนซ้ำก่อนที่จะบันทึกพวกมันทั้งหมดและวนซ้ำอีกครั้งสำหรับfor
ลูปของคุณ สิ่งเหล่านี้มักจะทำได้ดีกว่าเช่น:
iterator=$start
until [ "$((iterator+=interval))" -gt "$end" ]; do ...
... เนื่องจากคุณเก็บค่าเพียงไม่กี่ค่าและเขียนทับค่าเหล่านั้นในขณะที่คุณทำเช่นเดียวกับการทำซ้ำในขณะที่คุณสร้างค่า iterables
อย่างไรก็ตามเช่นเดียวกับการเว้นวรรคที่กล่าวถึงก่อนหน้านี้คุณยังสามารถใช้printf
zeropad เป็นจำนวนหลักได้ตามต้องการเช่น:
printf %05000d
ฉันทำทั้งสองอย่างโดยไม่มีข้อโต้แย้งเพราะสำหรับทุกอาร์กิวเมนต์ที่ระบุในprintf
สตริงรูปแบบของเมื่อข้อโต้แย้งไม่พบสตริงที่เป็นโมฆะถูกใช้ - ซึ่งถูกตีความว่าเป็นศูนย์สำหรับอาร์กิวเมนต์หลักหรือสตริงที่ว่างเปล่าสำหรับสตริง
นี่คือด้านอื่น ๆ(และ - ในความคิดของฉัน -ด้านประสิทธิภาพของเหรียญ) เมื่อเปรียบเทียบกับคำสั่งในคำถาม - ในขณะที่เป็นไปได้ที่จะไม่ได้อะไรจากสิ่งที่คุณทำเมื่อคุณprintf %.0
จำกัดความยาวของอาร์กิวเมนต์แต่ละข้อ เป็นไปได้ที่จะได้อะไรจากอะไร
ยังเร็วกว่าสำหรับจำนวนไบต์ที่สร้างขึ้นที่คุณสามารถใช้dd
เช่น:
printf \\0| dd bs=64k conv=sync
... และ w / ไฟล์ปกติdd
's seek=[num]
อาร์กิวเมนต์สามารถนำมาใช้ให้เป็นประโยชน์มากขึ้น คุณสามารถรับบรรทัดใหม่ 64k แทนที่จะเป็นโมฆะถ้าคุณเพิ่ม,unblock cbs=1
ไปด้านบนและจากนั้นสามารถฉีดสตริงตามอำเภอใจต่อบรรทัดด้วยpaste
และ/dev/null
- แต่ในกรณีนั้นถ้ามันพร้อมให้คุณคุณอาจใช้:
yes 'output string forever'
นี่คือdd
ตัวอย่างเพิ่มเติม:
dd bs=5000 seek=1 if=/dev/null of=./H.txt
... ซึ่งสร้าง(หรือตัดทอน)\0NUL
ไฟล์เต็มในไดเรกทอรีปัจจุบันชื่อ H.txt ขนาด 5000 ไบต์ dd
ค้นหาตรงไปยัง offset และ NUL เติมให้เต็ม
<&1 dd bs=5000 conv=sync,noerror count=1 | tr \\0 H >./H.txt
... ซึ่งสร้างไฟล์ที่มีชื่อและขนาดเดียวกัน แต่เติมตัวอักษร w / H จะใช้ประโยชน์จากdd
พฤติกรรม spec'd ของการเขียนออกมาอย่างน้อยหนึ่ง null บล็อกเต็มรูปแบบในกรณีของข้อผิดพลาดการอ่านเมื่อnoerror
และsync
แปลงที่ระบุไว้(และ - ไม่count=
- มีแนวโน้มที่จะไปนานกว่าที่คุณอาจต้องการ)และจงใจเปลี่ยนเส้นทาง ไฟล์อธิบายอย่างเป็นลายลักษณ์อักษรที่dd
stdin ของ
tcsh
หรือzsh
,repeat 5000 printf H
ง่ายต่อการเข้าใจ ด้วยperl
:print "H" x 5000
(โปรดทราบว่านั่น{1..5000}
คือตัวดำเนินการ zsh ที่ได้รับแรงบันดาลใจจากperl
's1..5000
และคัดลอกมาโดย ksh93 และ bash)