Printf कमांड का उपयोग करके एक वर्ण N को बार-बार लिखना


12

मुझे लिनक्स में एक चरित्र दोहराने के लिए निम्न आदेश मिला:

printf 'H%.0s' {1..5000} > H.txt

मैं उदाहरण के लिए, बार-बार Hदोहराना चाहता हूं 5000%.0sयहाँ क्या मतलब है?


साथ tcshया zsh, repeat 5000 printf Hसमझने के लिए आसान है। इसके साथ perl: print "H" x 5000(ध्यान दें कि {1..5000}यह एक zsh ऑपरेटर है जो बाद में ksh93 और bash द्वारा कॉपी किया गया है perl) से प्रेरित है1..5000
Stéphane Chazelas

हाँ यह काम करता है, लेकिन बड़े दोहराने के लिए बहुत सारे संसाधनों का उपयोग करता है, स्टीफन चेज़लस के सुझावों का पालन करें
स्केपरन

1
मैं यह आदेशyes H|head -5000|tr -d '\012'
स्कैपरन

dd if=/dev/zero bs=5000 count=1 | tr '\0' H
कोजिरो

@ सॅकेप्रेन:yes H| head -n 2500| tr \\n H
मिकसेर

जवाबों:


20

यह कमांड 5000 तर्क उत्पन्न करने वाले शेल पर निर्भर करता है, और उन्हें पास करने के printfबाद उन्हें अनदेखा कर देता है। हालांकि यह बहुत जल्दी लग सकता है - और कुछ चीजों के सापेक्ष है - शेल को अभी भी उन स्ट्रिंग्स के सभी उत्पन्न होना चाहिए (और उन्हें सीमांकित करें) और इसी तरह।

इस तथ्य के अलावा कि उत्पन्न Hs को तब तक मुद्रित नहीं किया जा सकता है जब तक कि शेल पहले 5000 तक पुनरावृत्त नहीं हो जाता है, उस आदेश में मेमोरी में वह सब भी शामिल होता है जो संख्यात्मक स्ट्रिंग तर्कों को printf प्लस Hs पर संग्रहीत करने और परिसीमन करने के लिए लेता है । बस के रूप में आप कर सकते हैं:

printf %05000s|tr \  H

... जो 5000 रिक्त स्थान की एक स्ट्रिंग उत्पन्न करता है - जो, कम से कम, आमतौर पर केवल एक बाइट प्रति है और कुछ भी खर्च नहीं करते हैं क्योंकि वे सीमांकित नहीं हैं। कुछ परीक्षणों से संकेत मिलता है कि यहां तक ​​कि कुछ के लिए 5000 बाइट्स कांटा की लागत और trइसके लिए आवश्यक पाइप भी इस मामले में इसके लायक है, और यह लगभग हमेशा होता है जब संख्या अधिक हो जाती है।

मैं भाग गया ...

time bash -c 'printf H%.0s {1..5000}' >/dev/null

...तथा...

time bash -c 'printf %05000s|tr \  H' >/dev/null

प्रत्येक के बारे में 5 बार एक टुकड़ा (यहां कुछ भी नहीं वैज्ञानिक - केवल उपाख्यानात्मक) और ब्रेस विस्तार संस्करण कुल प्रसंस्करण समय में .02 सेकंड से थोड़ा अधिक था, लेकिन trसंस्करण लगभग .012 सेकंड में औसतन आया - और trसंस्करण ने इसे हरा दिया। हर बार। मैं यह नहीं कह सकता कि मैं आश्चर्यचकित हूं - {brace expansion}एक उपयोगी इंटरैक्टिव शेल शॉर्टहैंड फीचर है, लेकिन आमतौर पर यह एक बेकार बात है जहां किसी भी तरह की स्क्रिप्टिंग का संबंध है। सामान्य रूप:

for i in {[num]..[num]}; do ...

... जब आप इसके बारे में सोचते हैं, तो वास्तव में दो for छोरें हैं - पहला आंतरिक है और इसमें निहित है कि शेल को किसी तरह से लूप करना चाहिए ताकि उन सभी को बचाने से पहले उन पुनरावृत्तियों को उत्पन्न किया जा सके और उन्हें आपके forलूप के लिए फिर से पुनरावृत्त किया जा सके । ऐसी चीजें आमतौर पर बेहतर की जाती हैं जैसे:

iterator=$start
until [ "$((iterator+=interval))" -gt "$end" ]; do ...

... क्योंकि आप केवल बहुत कम मूल्यों को संग्रहीत करते हैं और उन्हें अधिलेखित करते हैं जैसे ही आप पुनरावृति करते हैं और पुनरावृति करते समय पुनरावृत्ति करते हैं।

वैसे भी, पहले बताए गए स्थान की गद्दी की तरह, आप printfअंकों की एक मनमानी संख्या को फिर से खोलने के लिए भी उपयोग कर सकते हैं , निश्चित रूप से, जैसे:

printf %05000d

मैं तर्क के बिना दोनों करता हूं क्योंकि printfजब कोई तर्क नहीं मिलता है तो प्रारूप स्ट्रिंग में निर्दिष्ट प्रत्येक तर्क के लिए अशक्त स्ट्रिंग का उपयोग किया जाता है - जिसे एक अंक तर्क के लिए शून्य या स्ट्रिंग के लिए एक रिक्त स्ट्रिंग के रूप में व्याख्या की जाती है।

यह सिक्के का दूसरा (और - मेरी राय में - अधिक कुशल) पक्ष का है जब प्रश्न में आदेश के साथ तुलना की जाती है - जबकि किसी चीज से कुछ भी प्राप्त करना संभव नहीं है जब आप printf %.0प्रत्येक तर्क के लिए लंबाई बढ़ाते हैं, तो यह भी है कुछ नहीं से कुछ प्राप्त करना संभव है।

उत्पन्न बाइट्स की बड़ी मात्रा के लिए अभी भी आप इसका उपयोग कर सकते हैं dd:

printf \\0| dd bs=64k conv=sync 

... और w / नियमित फ़ाइलों ddका seek=[num]तर्क अधिक से अधिक लाभ के लिए इस्तेमाल किया जा सकता है। यदि आप ,unblock cbs=1ऊपर से जोड़ते हैं और आप के साथ प्रति पंक्ति मनमाने ढंग से तार इंजेक्षन कर सकते हैं pasteऔर /dev/null- लेकिन उस स्थिति में, यदि यह आपके लिए उपलब्ध है, तो आप उपयोग कर सकते हैं:

yes 'output string forever'

यहाँ कुछ और ddउदाहरण हैं:

dd bs=5000 seek=1 if=/dev/null of=./H.txt

... जो वर्तमान निर्देशिका में एक भरी हुई फ़ाइल बनाता है (या\0NUL आकार 5000 बाइट्स के H.txt नाम की निर्देशिका में )ddऑफसेट के लिए सीधे चाहता है और NUL- इसके पीछे सभी को भरता है।

<&1 dd bs=5000 conv=sync,noerror count=1 | tr \\0 H >./H.txt

... जो एक ही नाम और आकार की फ़ाइल बनाता है लेकिन w / H वर्णों को भर देता है। यह ddएक पढ़ने में त्रुटि के मामले में कम से कम एक पूर्ण अशक्त-ब्लॉक लिखने के व्यवहार का लाभ उठाता है जब noerrorऔर syncरूपांतरण निर्दिष्ट किए जाते हैं (और - बिना count=- संभवत: आप जितना चाहते थे उससे अधिक समय तक चलेगा) , और जानबूझकर पुनर्निर्देशन एक लिखित फाइल डिस्क्रिप्टर की स्टडिन पर dd


8

शून्य की सटीकता के साथ %.0sतर्क को एक स्ट्रिंग के रूप में परिवर्तित करने का साधन । के अनुसार , ऐसे मामले में सटीक मूल्य देता हैman 3 printf

   [ ... ] the  maximum  number  of characters to be printed from a
   string for s and S conversions.

इसलिए जब सटीकता शून्य होती है, तो स्ट्रिंग तर्क बिल्कुल भी मुद्रित नहीं होता है। हालाँकि, H(जो प्रारूप विनिर्देशक का एक हिस्सा है) कई बार मुद्रित हो जाता है, क्योंकि इसमें तर्क होते हैं, क्योंकि printfअनुभाग के अनुसारman bash

The format is reused as necessary to consume all  of  the  argu
ments.  If the format requires more arguments than are supplied,
the extra format specifications behave as if  a  zero  value  or
null  string,  as  appropriate,  had  been supplied. 

7

इस मामले में, %.0sहमेशा चरित्र के एक उदाहरण को प्रिंट करता है (पूर्व), इस मामले में एच। जब आप {1..5000} का उपयोग करते हैं, तो शेल इसका विस्तार करता है और यह बन जाता है:

printf 'H%.0s' 1 2 3 4 ... 5000 > H.txt

यानी, प्रिंटफ कमांड में अब 5000 तर्क हैं, और प्रत्येक तर्क के लिए, आपको एक एच मिलेगा। इनका अनुक्रम अनुक्रमिक संख्यात्मक होना जरूरी नहीं है:

printf 'H%.0s' a bc fg 12 34

प्रिंट HHHHH- अर्थात, इस मामले में तर्क की संख्या, 5।

ध्यान दें, ऊपर दिए गए 1 उदाहरण में एलिप्स को शाब्दिक रूप से सम्मिलित नहीं किया गया है, वे एक अनुक्रम या सीमा को इंगित करने के लिए वहां हैं।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.