मैं इसके साथ कैसे कर सकता था echo
?
perl -E 'say "=" x 100'
ruby -e 'puts "=" * 100'
याpython -c 'print "=" * 100'
printf
साथ में seq
)svrb=`printf '%.sv' $(seq $vrb)`
मैं इसके साथ कैसे कर सकता था echo
?
perl -E 'say "=" x 100'
ruby -e 'puts "=" * 100'
याpython -c 'print "=" * 100'
printf
साथ में seq
)svrb=`printf '%.sv' $(seq $vrb)`
जवाबों:
आप उपयोग कर सकते हैं:
printf '=%.0s' {1..100}
यह कैसे काम करता है:
बैश का विस्तार {1..100} हो जाता है, ताकि कमांड बन जाए:
printf '=%.0s' 1 2 3 4 ... 100
मैंने प्रिंटफ के प्रारूप को सेट कर दिया है, =%.0s
जिसका अर्थ है कि वह हमेशा एक ही प्रिंट करेगा =
चाहे वह कितना भी तर्क दे। इसलिए यह 100 =
एस प्रिंट करता है ।
repl = 100
उदाहरण के लिए लागू कर सकते हैं (उदाहरण के लिए eval
ट्रिकरी की आवश्यकता है, दुर्भाग्य से, एक चर पर ब्रेस विस्तार को आधार बनाने के लिए):repl() { printf "$1"'%.s' $(eval "echo {1.."$(($2))"}"); }
seq
इसके बजाय उदाहरण के लिए उपयोग करें $(seq 1 $limit)
।
$s%.0s
है %.0s$s
अन्यथा डैश एक printf
त्रुटि का कारण बनता है ।
printf
: यह तब तक प्रारूप स्ट्रिंग लागू करना जारी रखता है जब तक कि कोई तर्क शेष न हो। मैंने यह मान लिया था कि यह केवल एक बार प्रारूप स्ट्रिंग को संसाधित करेगा!
कोई आसान तरीका नहीं। लेकिन उदाहरण के लिए:
seq -s= 100|tr -d '[:digit:]'
या शायद एक मानक-अनुरूप तरीका:
printf %100s |tr " " "="
वहाँ भी है tput rep
, लेकिन हाथ (xterm और linux) पर मेरे टर्मिनलों के लिए के रूप में वे इसे समर्थन नहीं करते :)
=
वर्णों को प्रिंट करेगा ।
printf
tr
केवल POSIX समाधान है क्योंकि seq
, yes
और {1..3}
POSIX नहीं हैं।
printf %100s | sed 's/ /abc/g'
- आउटपुट 'एब्काबैबक ...'
tr
) का उपयोग करने के लिए +1 । आप इसे कुछ इस तरह बढ़ा सकते हैं printf "%${COLUMNS}s\n" | tr " " "="
।
wc
। एकमात्र निष्कर्ष जो मैं इससे ले सकता हूं वह है "का seq
उपयोग नहीं किया जाना चाहिए"।
अपने इनपुट के लिए @ gniourf_gniourf को टोपी की टिप दें ।
नोट: यह उत्तर मूल प्रश्न का उत्तर नहीं देता है , लेकिन प्रदर्शन की तुलना करके मौजूदा, सहायक उत्तरों का पूरक है ।
केवल निष्पादन की गति के संदर्भ में समाधानों की तुलना की जाती है - स्मृति आवश्यकताओं को ध्यान में नहीं रखा जाता है (वे समाधानों में भिन्न होते हैं और बड़े दोहराव के मायने रखते हैं)।
सारांश:
${var// /=}
) के साथ बैश के वैश्विक प्रतिस्थापन प्रतिस्थापन से बचें , क्योंकि यह निषेधात्मक रूप से धीमा है।निम्नलिखित हैं समय एक 3.2 गीगा इंटेल कोर i5 सीपीयू और एक फ्यूजन ड्राइव, OSX 10.10.4 और बैश 3.2.57 चल के साथ एक देर से 2012 आईमैक पर ले लिया है, और 1000 रन की औसत रहे हैं।
प्रविष्टियां हैं:
M
... एक संभावित बहु -वर्ण समाधानS
... एक एकल -एकमात्र समाधानP
... एक POSIX- अनुरूप समाधान[M, P] printf %.s= [dogbane]: 0.0002
[M ] printf + bash global substr. replacement [Tim]: 0.0005
[M ] echo -n - brace expansion loop [eugene y]: 0.0007
[M ] echo -n - arithmetic loop [Eliah Kagan]: 0.0013
[M ] seq -f [Sam Salisbury]: 0.0016
[M ] jot -b [Stefan Ludwig]: 0.0016
[M ] awk - $(count+1)="=" [Steven Penny (variant)]: 0.0019
[M, P] awk - while loop [Steven Penny]: 0.0019
[S ] printf + tr [user332325]: 0.0021
[S ] head + tr [eugene y]: 0.0021
[S, P] dd + tr [mklement0]: 0.0021
[M ] printf + sed [user332325 (comment)]: 0.0021
[M ] mawk - $(count+1)="=" [Steven Penny (variant)]: 0.0025
[M, P] mawk - while loop [Steven Penny]: 0.0026
[M ] gawk - $(count+1)="=" [Steven Penny (variant)]: 0.0028
[M, P] gawk - while loop [Steven Penny]: 0.0028
[M ] yes + head + tr [Digital Trauma]: 0.0029
[M ] Perl [sid_com]: 0.0059
awk
, और perl
समाधान से बचें ।[M ] Perl [sid_com]: 0.0067
[M ] mawk - $(count+1)="=" [Steven Penny (variant)]: 0.0254
[M ] gawk - $(count+1)="=" [Steven Penny (variant)]: 0.0599
[S ] head + tr [eugene y]: 0.1143
[S, P] dd + tr [mklement0]: 0.1144
[S ] printf + tr [user332325]: 0.1164
[M, P] mawk - while loop [Steven Penny]: 0.1434
[M ] seq -f [Sam Salisbury]: 0.1452
[M ] jot -b [Stefan Ludwig]: 0.1690
[M ] printf + sed [user332325 (comment)]: 0.1735
[M ] yes + head + tr [Digital Trauma]: 0.1883
[M, P] gawk - while loop [Steven Penny]: 0.2493
[M ] awk - $(count+1)="=" [Steven Penny (variant)]: 0.2614
[M, P] awk - while loop [Steven Penny]: 0.3211
[M, P] printf %.s= [dogbane]: 2.4565
[M ] echo -n - brace expansion loop [eugene y]: 7.5877
[M ] echo -n - arithmetic loop [Eliah Kagan]: 13.5426
[M ] printf + bash global substr. replacement [Tim]: n/a
${foo// /=}
) बेवजह बड़े स्ट्रिंग्स के साथ धीमी गति से होता है, और बैश 4.3.30 में (लगभग 50 मिनट!) रनिंग से बाहर ले जाया गया है, और बैश 3.2.57 में भी लंबे समय तक! मैंने कभी इंतजार नहीं किया। इसे समाप्त करना)।(( i= 0; ... ))
) ब्रेस-विस्तारित वाले की तुलना में धीमे होते हैं ( {1..n}
) - हालांकि अंकगणितीय लूप अधिक मेमोरी-कुशल होते हैं।awk
बीएसडी को संदर्भित करता है awk
(जैसा कि OSX पर भी पाया गया है) - यह gawk
(GNU Awk) की तुलना में विशेष रूप से धीमा है और विशेष रूप से mawk
।यहाँ बैश लिपि ( testrepeat
) है जो उपरोक्त उत्पादन करती है। इसमें 2 तर्क दिए गए हैं:
दूसरे शब्दों में: ऊपर दिए गए समय के साथ testrepeat 100 1000
और प्राप्त किए गए थेtestrepeat 1000000 1000
#!/usr/bin/env bash
title() { printf '%s:\t' "$1"; }
TIMEFORMAT=$'%6Rs'
# The number of repetitions of the input chars. to produce
COUNT_REPETITIONS=${1?Arguments: <charRepeatCount> [<testRunCount>]}
# The number of test runs to perform to derive the average timing from.
COUNT_RUNS=${2:-1}
# Discard the (stdout) output generated by default.
# If you want to check the results, replace '/dev/null' on the following
# line with a prefix path to which a running index starting with 1 will
# be appended for each test run; e.g., outFilePrefix='outfile', which
# will produce outfile1, outfile2, ...
outFilePrefix=/dev/null
{
outFile=$outFilePrefix
ndx=0
title '[M, P] printf %.s= [dogbane]'
[[ $outFile != '/dev/null' ]] && outFile="$outFilePrefix$((++ndx))"
# !! In order to use brace expansion with a variable, we must use `eval`.
eval "
time for (( n = 0; n < COUNT_RUNS; n++ )); do
printf '%.s=' {1..$COUNT_REPETITIONS} >"$outFile"
done"
title '[M ] echo -n - arithmetic loop [Eliah Kagan]'
[[ $outFile != '/dev/null' ]] && outFile="$outFilePrefix$((++ndx))"
time for (( n = 0; n < COUNT_RUNS; n++ )); do
for ((i=0; i<COUNT_REPETITIONS; ++i)); do echo -n =; done >"$outFile"
done
title '[M ] echo -n - brace expansion loop [eugene y]'
[[ $outFile != '/dev/null' ]] && outFile="$outFilePrefix$((++ndx))"
# !! In order to use brace expansion with a variable, we must use `eval`.
eval "
time for (( n = 0; n < COUNT_RUNS; n++ )); do
for i in {1..$COUNT_REPETITIONS}; do echo -n =; done >"$outFile"
done
"
title '[M ] printf + sed [user332325 (comment)]'
[[ $outFile != '/dev/null' ]] && outFile="$outFilePrefix$((++ndx))"
time for (( n = 0; n < COUNT_RUNS; n++ )); do
printf "%${COUNT_REPETITIONS}s" | sed 's/ /=/g' >"$outFile"
done
title '[S ] printf + tr [user332325]'
[[ $outFile != '/dev/null' ]] && outFile="$outFilePrefix$((++ndx))"
time for (( n = 0; n < COUNT_RUNS; n++ )); do
printf "%${COUNT_REPETITIONS}s" | tr ' ' '=' >"$outFile"
done
title '[S ] head + tr [eugene y]'
[[ $outFile != '/dev/null' ]] && outFile="$outFilePrefix$((++ndx))"
time for (( n = 0; n < COUNT_RUNS; n++ )); do
head -c $COUNT_REPETITIONS < /dev/zero | tr '\0' '=' >"$outFile"
done
title '[M ] seq -f [Sam Salisbury]'
[[ $outFile != '/dev/null' ]] && outFile="$outFilePrefix$((++ndx))"
time for (( n = 0; n < COUNT_RUNS; n++ )); do
seq -f '=' -s '' $COUNT_REPETITIONS >"$outFile"
done
title '[M ] jot -b [Stefan Ludwig]'
[[ $outFile != '/dev/null' ]] && outFile="$outFilePrefix$((++ndx))"
time for (( n = 0; n < COUNT_RUNS; n++ )); do
jot -s '' -b '=' $COUNT_REPETITIONS >"$outFile"
done
title '[M ] yes + head + tr [Digital Trauma]'
[[ $outFile != '/dev/null' ]] && outFile="$outFilePrefix$((++ndx))"
time for (( n = 0; n < COUNT_RUNS; n++ )); do
yes = | head -$COUNT_REPETITIONS | tr -d '\n' >"$outFile"
done
title '[M ] Perl [sid_com]'
[[ $outFile != '/dev/null' ]] && outFile="$outFilePrefix$((++ndx))"
time for (( n = 0; n < COUNT_RUNS; n++ )); do
perl -e "print \"=\" x $COUNT_REPETITIONS" >"$outFile"
done
title '[S, P] dd + tr [mklement0]'
[[ $outFile != '/dev/null' ]] && outFile="$outFilePrefix$((++ndx))"
time for (( n = 0; n < COUNT_RUNS; n++ )); do
dd if=/dev/zero bs=$COUNT_REPETITIONS count=1 2>/dev/null | tr '\0' "=" >"$outFile"
done
# !! On OSX, awk is BSD awk, and mawk and gawk were installed later.
# !! On Linux systems, awk may refer to either mawk or gawk.
for awkBin in awk mawk gawk; do
if [[ -x $(command -v $awkBin) ]]; then
title "[M ] $awkBin"' - $(count+1)="=" [Steven Penny (variant)]'
[[ $outFile != '/dev/null' ]] && outFile="$outFilePrefix$((++ndx))"
time for (( n = 0; n < COUNT_RUNS; n++ )); do
$awkBin -v count=$COUNT_REPETITIONS 'BEGIN { OFS="="; $(count+1)=""; print }' >"$outFile"
done
title "[M, P] $awkBin"' - while loop [Steven Penny]'
[[ $outFile != '/dev/null' ]] && outFile="$outFilePrefix$((++ndx))"
time for (( n = 0; n < COUNT_RUNS; n++ )); do
$awkBin -v count=$COUNT_REPETITIONS 'BEGIN { while (i++ < count) printf "=" }' >"$outFile"
done
fi
done
title '[M ] printf + bash global substr. replacement [Tim]'
[[ $outFile != '/dev/null' ]] && outFile="$outFilePrefix$((++ndx))"
# !! In Bash 4.3.30 a single run with repeat count of 1 million took almost
# !! 50 *minutes*(!) to complete; n Bash 3.2.57 it's seemingly even slower -
# !! didn't wait for it to finish.
# !! Thus, this test is skipped for counts that are likely to be much slower
# !! than the other tests.
skip=0
[[ $BASH_VERSINFO -le 3 && COUNT_REPETITIONS -gt 1000 ]] && skip=1
[[ $BASH_VERSINFO -eq 4 && COUNT_REPETITIONS -gt 10000 ]] && skip=1
if (( skip )); then
echo 'n/a' >&2
else
time for (( n = 0; n < COUNT_RUNS; n++ )); do
{ printf -v t "%${COUNT_REPETITIONS}s" '='; printf %s "${t// /=}"; } >"$outFile"
done
fi
} 2>&1 |
sort -t$'\t' -k2,2n |
awk -F $'\t' -v count=$COUNT_RUNS '{
printf "%s\t", $1;
if ($2 ~ "^n/a") { print $2 } else { printf "%.4f\n", $2 / count }}' |
column -s$'\t' -t
In order to use brace expansion with a variable, we must use `eval`
B
इसे करने का एक से अधिक तरीका है।
एक लूप का उपयोग करना:
ब्रेस विस्तार का उपयोग पूर्णांक शाब्दिक के साथ किया जा सकता है:
for i in {1..100}; do echo -n =; done
C- जैसा लूप वैरिएबल के उपयोग की अनुमति देता है:
start=1
end=100
for ((i=$start; i<=$end; i++)); do echo -n =; done
printf
बिलिन का उपयोग करना :
printf '=%.0s' {1..100}
यहां एक सटीक निर्दिष्ट करना निर्दिष्ट चौड़ाई ( 0
) को फिट करने के लिए स्ट्रिंग को काटता है । जैसा कि printf
सभी तर्कों का उपभोग करने के लिए प्रारूप स्ट्रिंग का पुन: उपयोग होता है, यह केवल "="
100 बार प्रिंट करता है।
का उपयोग कर head
(और printf
,) और tr
:
head -c 100 < /dev/zero | tr '\0' '='
printf %100s | tr " " "="
head
/ tr
समाधान, जो उच्च दोहराने वाली गणनाओं के साथ भी अच्छी तरह से काम करता है (छोटा चेतावनी: head -c
पोसिक्स-अनुपालन नहीं है, लेकिन बीएसडी और जीएनयू दोनों head
इसे लागू करते हैं); जबकि उस मामले में अन्य दो समाधान धीमी गति से होंगे, उनके पास मल्टी- स्ट्रैचर स्ट्रिंग्स के साथ काम करने का लाभ भी है।
yes
और head
उपयोगी है yes "" | head -n 100
:। tr
किसी भी चरित्र को मुद्रित कर सकते हैं:yes "" | head -n 100 | tr "\n" "="; echo
dd if=/dev/zero count=1 bs=100000000 | tr '\0' '=' >/dev/null
की तुलना में काफी धीमी है head -c100000000 < /dev/zero | tr '\0' '=' >/dev/null
। निश्चित रूप से समय अंतर को यथोचित रूप से मापने के लिए आपको 100M + के ब्लॉक आकार का उपयोग करना होगा। 100M बाइट्स दिखाए गए दो संबंधित संस्करणों के साथ 1.7 s और 1 s लेता है। मैंने ट्राई को उतार दिया और बस इसे डंप कर दिया /dev/null
और head
संस्करण के लिए 0.287 और dd
एक बिलियन बाइट्स के लिए संस्करण के लिए 0.675 एस प्राप्त किया ।
dd if=/dev/zero count=1 bs=100000000 | tr '\0' '=' >/dev/null
=> 0,21332 s, 469 MB/s
; के लिए: dd if=/dev/zero count=100 bs=1000000| tr '\0' '=' >/dev/null
=> 0,161579 s, 619 MB/s
;
मैं बस seq का उपयोग कर यह करने के लिए एक गंभीरता से आसान तरीका मिल गया है:
अद्यतन: यह बीएसडी पर काम करता है जो seq
अन्य संस्करणों के साथ ओएस एक्स वाईएमएमवी के साथ आता है
seq -f "#" -s '' 10
इस तरह 10 बार '#' प्रिंट करेंगे:
##########
-f "#"
संख्याओं को अनदेखा करने के लिए प्रारूप स्ट्रिंग सेट करता है और बस #
प्रत्येक के लिए प्रिंट करता है।-s ''
प्रत्येक नंबर के बीच आवेषण seq आवेषण को निकालने के लिए विभाजक को एक रिक्त स्ट्रिंग में सेट करता है-f
और -s
महत्वपूर्ण होने लगते हैं।संपादित करें: यहाँ यह एक आसान कार्य में है ...
repeat () {
seq -f $1 -s '' $2; echo
}
जिसे आप इस तरह से कॉल कर सकते हैं ...
repeat "#" 10
नोट: यदि आप दोहरा रहे हैं #
तो उद्धरण महत्वपूर्ण हैं!
seq: format ‘#’ has no % directive
। seq
संख्या के लिए है, तार नहीं। Gnu.org/software/coreutils/manual/html_node/seq-invocation.html
seq
को यहां चतुराई से दोहराया जा रहा है : प्रारूप स्ट्रिंग को पास किया गया - सामान्य रूप से उत्पन्न होने वाली संख्याओं को प्रारूपित करने के लिए उपयोग किया जाता है - यहां केवल स्ट्रिंग को दोहराने के लिए होता है ताकि आउटपुट में केवल उस स्ट्रिंग की प्रतियां शामिल हों। दुर्भाग्य से, GNU प्रारूप स्ट्रिंग में एक संख्या प्रारूप की उपस्थिति पर जोर देता है , जो कि आप देख रहे त्रुटि है। -f
seq
"$1"
(दोहरे उद्धरण चिह्नों) का उपयोग करें , ताकि आप वर्णों में भी पास हो सकें '*'
और एम्बेडेड व्हाट्सएप के साथ तार कर सकें । अंत में, यदि आप उपयोग करने के लिए सक्षम होना चाहते हैं %
, तो आप के लिए है दोगुना यह (अन्यथा seq
होगा लगता है कि यह इस तरह के रूप में एक प्रारूप विनिर्देश का हिस्सा %f
); का उपयोग कर "${1//%/%%}"
ध्यान रखना होगा। चूंकि (जैसा कि आप उल्लेख करते हैं) आप बीएसडी का उपयोग कर रहे हैं seq
, यह सामान्य रूप से बीएसडी जैसे ओएस पर काम करेगा (उदाहरण के लिए, फ्रीबीएसडी) - इसके विपरीत, यह लिनक्स पर काम नहीं करेगा , जहां जीएनयू seq
का उपयोग किया जाता है।
यहाँ दो दिलचस्प तरीके हैं:
ubuntu @ ubuntu: ~ $ हां = | सिर -10 | पेस्ट -s -d '' - ========== ubuntu @ ubuntu: ~ $ हां = | सिर -10 | tr -d "\ n" ========== ubuntu @ ubuntu: ~ $
ध्यान दें कि ये दोनों अलग-अलग हैं - paste
विधि एक नई पंक्ति में समाप्त होती है। tr
विधि नहीं है।
paste
अनिवार्य रूप से आवश्यकता होती -d '\0'
है, और इसके साथ विफल हो जाता है -d ''
- -d '\0'
सभी पोसिक्स-संगत paste
कार्यान्वयनों को काम करना चाहिए और वास्तव में जीएनयू के साथ paste
भी काम करना चाहिए।
yes | mapfile -n 100 -C 'printf = \#' -c 1
time yes = | head -500 | paste -s -d '\0' -; time yes | mapfile -n 500 -C 'printf = \#' -c 1
। अधिक महत्वपूर्ण बात, हालांकि: यदि आप किसी printf
भी तरह का उपयोग कर रहे हैं , तो आप स्वीकार किए गए उत्तर से दोनों सरल और अधिक कुशल दृष्टिकोण के साथ जा सकते हैं:printf '%.s=' $(seq 500)
कोई सरल तरीका नहीं है। उपयोग printf
और प्रतिस्थापन से छोरों से बचें ।
str=$(printf "%40s")
echo ${str// /rep}
# echoes "rep" 40 times.
repl = 100
उदाहरण के लिए, (एक अनुगामी आउटपुट नहीं है \n
) के रूप में लागू किया जा सकता है :repl() { local ts=$(printf "%${2}s"); printf %s "${ts// /$1}"; }
यदि आप POSIX- अनुपालन और निरंतरता के विभिन्न कार्यान्वयनों में echo
और printf
, और / या केवल के अलावा अन्य गोले चाहते हैं bash
:
seq(){ n=$1; while [ $n -le $2 ]; do echo $n; n=$((n+1)); done ;} # If you don't have it.
echo $(for each in $(seq 1 100); do printf "="; done)
... उत्पादन के perl -E 'say "=" x 100'
बारे में हर जगह के रूप में ही उत्पादन होगा ।
seq
एक पॉसिक्स उपयोगिता नहीं है (हालांकि बीएसडी और लिनक्स सिस्टम के पास इसके कार्यान्वयन हैं) - आप while
@ Xennex81 के उत्तर में (जैसे printf "="
, जैसा कि आप सही ढंग से सुझाव देते हैं, बजाय echo -n
) , लूप के साथ पॉसिक्स शेल अंकगणित कर सकते हैं ।
cal
POSIX है। seq
नहीं है। वैसे भी, थोड़ी देर के पाश के साथ उत्तर को फिर से लिखने के बजाय (जैसा कि आप कहते हैं, यह पहले से ही अन्य उत्तरों में है) मैं एक RYO फ़ंक्शन जोड़ूंगा। इस तरह से अधिक शैक्षिक ;-)।
सवाल यह था कि इसे कैसे किया जाए echo
:
echo -e ''$_{1..100}'\b='
यह ठीक वैसा ही करेगा, perl -E 'say "=" x 100'
लेकिन echo
केवल उसी के साथ ।
कोई नहीं eval
, कोई उपधारा, कोई बाहरी उपकरण, कोई ब्रेस विस्तार (यानी, आपके पास चर में दोहराने के लिए संख्या हो सकती है) के साथ एक शुद्ध बैश रास्ता :
यदि आपको एक चर दिया जाता है n
जो एक (गैर-ऋणात्मक) संख्या और एक चर pattern
, जैसे,
$ n=5
$ pattern=hello
$ printf -v output '%*s' "$n"
$ output=${output// /$pattern}
$ echo "$output"
hellohellohellohellohello
आप इसके साथ एक फंक्शन कर सकते हैं:
repeat() {
# $1=number of patterns to repeat
# $2=pattern
# $3=output variable name
local tmp
printf -v tmp '%*s' "$1"
printf -v "$3" '%s' "${tmp// /$2}"
}
इस सेट के साथ:
$ repeat 5 hello output
$ echo "$output"
hellohellohellohellohello
इस छोटी सी ट्रिक के लिए हम इसके printf
साथ काफी प्रयोग कर रहे हैं :
-v varname
: मानक आउटपुट पर मुद्रण के बजाय, printf
स्वरूपित स्ट्रिंग की सामग्री को चर में डाल देगा varname
।printf
रिक्त स्थान की संबंधित संख्या को मुद्रित करने के लिए तर्क का उपयोग करेगा। जैसे, printf '%*s' 42
४२ स्थान छपेंगे।${var// /$pattern}
के var
साथ विस्तार होगा $pattern
।आप अप्रत्यक्ष विस्तार का उपयोग करके फ़ंक्शन tmp
में चर से छुटकारा पा सकते हैं repeat
:
repeat() {
# $1=number of patterns to repeat
# $2=pattern
# $3=output variable name
printf -v "$3" '%*s' "$1"
printf -v "$3" '%s' "${!3// /$2}"
}
bash
पैरामीटर विस्तार ( ${var//old/new}
) के संदर्भ में वैश्विक स्ट्रिंग प्रतिस्थापन ऑपरेशन विशेष रूप से धीमे हैं: बैश 3.2.57
में धीरे-धीरे धीमी गति से और बैश में धीमी गति से 4.3.30
, कम से कम मेरे OSX 10.10.3 सिस्टम पर 3.2 Ghz इंटेल कोर i5 मशीन पर। 1,000 की गिनती, चीजें धीमी हैं ( 3.2.57
) / तेज ( 4.3.30
): 0.1 / 0.004 सेकंड। संख्या में 10,000 पैदावार बढ़ाने के लिए अलग-अलग संख्या में: repeat 10000 = var
लगभग 80 सेकंड (!) को bash में 3.2.57
, और लगभग 0.3 सेकंड को bash में 4.3.30
(बहुत तेज़ी से 3.2.57
, लेकिन फिर भी धीमा)।
#!/usr/bin/awk -f
BEGIN {
OFS = "="
NF = 100
print
}
या
#!/usr/bin/awk -f
BEGIN {
while (z++ < 100) printf "="
}
awk 'BEGIN { while (c++ < 100) printf "=" }'
:। एक पैरामीटर किए गए शेल फ़ंक्शन में लिपटे ( repeat 100 =
उदाहरण के लिए, इनवोक करें ) repeat() { awk -v count="$1" -v txt=".$2" 'BEGIN { txt=substr(txt, 2); while (i++ < count) printf txt }'; }
:। (डमी .
उपसर्ग चार और पूरक substr
कॉल बीएसडी में एक बग के आसपास काम करने के लिए आवश्यक है awk
, जहां एक चर मान है जो कमांड को तोड़ने के साथ शुरू होता है=
।)
NF = 100
समाधान (हालांकि 100 पाने के लिए बहुत चालाक है =
, आप का उपयोग करना चाहिए NF = 101
)। चेतावनी यह है कि यह BSD को क्रैश कर देता है awk
(लेकिन यह बहुत तेज़ है gawk
और इसके साथ और भी तेज़ है mawk
), और यह कि POSIX न तो असाइनमेंट करता है NF
, न ही BEGIN
ब्लॉकों में खेतों का उपयोग करता है । आप इसे बीएसडी के awk
साथ-साथ एक मामूली ट्वीक के साथ भी बना सकते हैं : awk 'BEGIN { OFS = "="; $101=""; print }'
(लेकिन उत्सुकता से, बीएसडी में awk
जो लूप समाधान से तेज नहीं है)। एक पैरामीटर शेल समाधान के रूप में repeat() { awk -v count="$1" -v txt=".$2" 'BEGIN { OFS=substr(txt, 2); $(count+1)=""; print }'; }
:।
original-awk
बीएसडी के awk, जो भी, क्रैश हुआ हो तो आप इस कोशिश करना चाहते हैं सूचित किया गया है के लिए इसी तरह पुराने awk का लिनक्स के तहत नाम है। ध्यान दें कि दुर्घटनाग्रस्त होना आमतौर पर एक शोषक बग को खोजने की दिशा में पहला कदम है। यह उत्तर असुरक्षित कोड को बढ़ावा दे रहा है।
original-awk
गैर मानक है और अनुशंसित नहीं है
awk NF=100 OFS='=' <<< ""
(उपयोग करना bash
और gawk
)
मुझे लगता है कि प्रश्न का मूल उद्देश्य केवल शेल के अंतर्निहित कमांड के साथ ऐसा करना था। तो for
छोरों और printf
रों, वैध होगा, जबकि rep
, perl
, और भी jot
नीचे नहीं होगा। फिर भी, निम्नलिखित आदेश
jot -s "/" -b "\\" $((COLUMNS/2))
उदाहरण के लिए, खिड़की की चौड़ी लाइन प्रिंट करता है \/\/\/\/\/\/\/\/\/\/\/\/
jot -s '' -b '=' 100
:। चेतावनी यह है कि BSD जैसे प्लेटफॉर्म, OSX सहित jot
, लिनक्स डिस्ट्रोस के साथ नहीं आते हैं ।
apt install athena-jot
प्रदान करेगा jot
।
जैसा कि अन्य लोगों ने कहा है, बैश ब्रेस में एक्सपोज़र पैरामीटर विस्तार से पहले होता है , इसलिए रेंज में केवल शाब्दिक शामिल हो सकते हैं। और स्वच्छ समाधान प्रदान करते हैं, लेकिन एक सिस्टम से दूसरे सिस्टम में पूरी तरह से पोर्टेबल नहीं हैं, भले ही आप प्रत्येक पर समान शेल का उपयोग कर रहे हों। (हालांकि तेजी से उपलब्ध है, उदाहरण के लिए, FreeBSD 9.3 और उच्चतर में ।) और अप्रत्यक्ष के अन्य रूप हमेशा काम करते हैं, लेकिन कुछ हद तक असंगत हैं।{m,n}
seq
jot
seq
eval
सौभाग्य से, बैश छोरों के लिए सी-शैली का समर्थन करता है (केवल अंकगणितीय अभिव्यक्तियों के साथ)। तो यहाँ एक संक्षिप्त "शुद्ध बैश" तरीका है:
repecho() { for ((i=0; i<$1; ++i)); do echo -n "$2"; done; echo; }
यह पहले तर्क के रूप में दोहराव की संख्या लेता है और दूसरे तर्क के रूप में दोहराया जाने वाला स्ट्रिंग (जो एकल वर्ण हो सकता है, जैसा कि समस्या वर्णन में है)। repecho 7 b
आउटपुट bbbbbbb
(एक नई लाइन द्वारा समाप्त)।
डेनिस विलियमसन दिया अनिवार्य रूप से अपने उत्कृष्ट जवाब में चार साल पहले इस समाधान के लिए खोल स्क्रिप्ट में दोहराया वर्णों की स्ट्रिंग बनाना । मेरा फ़ंक्शन बॉडी वहां के कोड से थोड़ा अलग है:
चूँकि यहाँ ध्यान एक ही चरित्र को दोहराने पर है और शेल बैश है, इसलिए संभवतः echo
इसके बजाय इसका उपयोग करना सुरक्षित है printf
। और मैंने इस प्रश्न में समस्या के वर्णन को पढ़ने के लिए प्राथमिकता दी है echo
। उपरोक्त फ़ंक्शन परिभाषा बैश और ksh93 में काम करती है । यद्यपि printf
अधिक पोर्टेबल है (और आमतौर पर इस तरह की चीज के लिए इस्तेमाल किया जाना चाहिए), echo
वाक्यविन्यास यकीनन अधिक पठनीय है।
कुछ गोले का निर्माण अपने आप में एक विकल्प के रूप में echo
व्याख्या -
करता है - भले ही -
इनपुट के लिए स्टड का उपयोग करने का सामान्य अर्थ , के लिए बकवास है echo
। zsh यह करता है। और निश्चित रूप से मौजूद है echo
कि यह पहचान नहीं है -n
, क्योंकि यह मानक नहीं है । (कई बॉर्न-शैली के गोले छोरों के लिए सी-शैली को बिल्कुल स्वीकार नहीं करते हैं, इस प्रकार उनके echo
व्यवहार पर विचार नहीं किया जाना चाहिए ..)
यहां कार्य अनुक्रम को प्रिंट करना है; वहाँ , यह एक चर के लिए आवंटित करने के लिए किया गया था।
यदि $n
पुनरावृत्ति की वांछित संख्या है और आपको इसका पुन: उपयोग नहीं करना है, और आप कुछ कम चाहते हैं:
while ((n--)); do echo -n "$s"; done; echo
n
एक चर होना चाहिए - इस तरह से स्थितिगत मापदंडों के साथ काम नहीं करता है। $s
पाठ दोहराया जाना है।
printf "%100s" | tr ' ' '='
इष्टतम है।
zsh
संयोगवश, साथ ही साथ काम करता है । इको-इन-लूप दृष्टिकोण छोटे रिपीट काउंट्स के लिए अच्छी तरह से काम करता है, लेकिन बड़े लोगों के लिए पोसिक्स-कंप्लायंट विकल्प हैं जो उपयोगिताओं पर आधारित हैं , जैसा कि @ Slomojo की टिप्पणी से स्पष्ट है।
(while ((n--)); do echo -n "$s"; done; echo)
echo
बिलिन है जो समर्थन करता है -n
। आप जो कह रहे हैं उसकी भावना बिलकुल सही है। कम से कम गैर-इंटरैक्टिव उपयोग में printf
लगभग हमेशा पसंद किया जाना चाहिए echo
। लेकिन मुझे नहीं लगता कि यह किसी भी तरह से अनुचित या भ्रामक था, जो किसी echo
एक प्रश्न का उत्तर देने के लिए था और जिसने यह जानने के लिए पर्याप्त जानकारी दी कि यह काम करेगा । कृपया यह भी ध्यान दें कि ((n--))
(बिना $
) के समर्थन के लिए खुद POSIX द्वारा गारंटी नहीं दी जाती है।
अजगर सर्वव्यापी है और हर जगह समान काम करता है।
python -c "import sys; print('*' * int(sys.argv[1]))" "=" 100
चरित्र और गिनती को अलग-अलग मापदंडों के रूप में पारित किया जाता है।
python -c "import sys; print(sys.argv[1] * int(sys.argv[2]))" "=" 100
एक और मनमाना स्ट्रिंग n बार दोहराने का मतलब है:
पेशेवरों:
विपक्ष:
yes
कमांड की आवश्यकता है।#!/usr/bin/sh
to_repeat='='
repeat_count=80
yes "$to_repeat" | tr -d '\n' | head -c "$repeat_count"
ANSI टर्मिनल और US-ASCII वर्णों को दोहराने के लिए। आप एक एएनएसआई सीएसआई एस्केप सीक्वेंस का उपयोग कर सकते हैं। किसी चरित्र को दोहराना सबसे तेज़ तरीका है।
#!/usr/bin/env bash
char='='
repeat_count=80
printf '%c\e[%db' "$char" "$repeat_count"
या वैधानिक रूप से:
80 बार की एक पंक्ति प्रिंट करें =
:
printf '=\e[80b\n'
सीमाएं:
repeat_char
ANSI CSI अनुक्रम को नहीं समझते हैं ।repeat_char
करना बार-बार वर्ण में ANSI CSI अनुक्रम का विस्तार नहीं करेगा ।यहाँ मैं लिनक्स में स्क्रीन पर वर्णों की एक पंक्ति को प्रिंट करने के लिए उपयोग करता हूं (टर्मिनल / स्क्रीन की चौड़ाई के आधार पर)
printf '=%.0s' $(seq 1 $(tput cols))
स्पष्टीकरण:
दिए गए अनुक्रम के रूप में कई बार एक समान चिह्न प्रिंट करें:
printf '=%.0s' #sequence
कमांड के आउटपुट का उपयोग करें (यह कमांड सब्सट्रेशन नामक एक बैश फीचर है):
$(example_command)
एक अनुक्रम दें, मैंने उदाहरण के रूप में 1 से 20 का उपयोग किया है। अंतिम कमांड में 20 के बजाय tput कमांड का उपयोग किया जाता है:
seq 1 20
वर्तमान में टर्मिनल में उपयोग किए जाने वाले स्तंभों की संख्या दें:
tput cols
for i in {1..100}
do
echo -n '='
done
echo
उस स्थिति में, जब आप किसी वर्ण को दोहराना चाहते हैं, तो यह कहते हुए कि आपके द्वारा की जा सकने वाली स्ट्रिंग की लंबाई:
#!/bin/bash
vari='AB'
n=$(expr 10 - length $vari)
echo 'vari equals.............................: '$vari
echo 'Up to 10 positions I must fill with.....: '$n' equal signs'
echo $vari$(perl -E 'say "=" x '$n)
यह प्रदर्शित करता है:
vari equals.............................: AB
Up to 10 positions I must fill with.....: 8 equal signs
AB========
length
साथ काम नहीं करेगा expr
, आप शायद मतलब था n=$(expr 10 - ${#vari})
; हालांकि, यह बाश के अंकगणितीय विस्तार का उपयोग करने के लिए सरल और अधिक कुशल है n=$(( 10 - ${#vari} ))
:। इसके अलावा, आपके उत्तर के मूल में बहुत पर्ल दृष्टिकोण है जो ओपी को बैश विकल्प की तलाश में है।
यह एलिया कगन की जासूसी का लंबा संस्करण है:
while [ $(( i-- )) -gt 0 ]; do echo -n " "; done
बेशक आप उस के लिए भी प्रिंटफ का उपयोग कर सकते हैं, लेकिन वास्तव में मेरी पसंद के अनुसार नहीं:
printf "%$(( i*2 ))s"
यह संस्करण डैश संगत है:
until [ $(( i=i-1 )) -lt 0 ]; do echo -n " "; done
मैं प्रारंभिक संख्या होने के साथ।
function repeatString()
{
local -r string="${1}"
local -r numberToRepeat="${2}"
if [[ "${string}" != '' && "${numberToRepeat}" =~ ^[1-9][0-9]*$ ]]
then
local -r result="$(printf "%${numberToRepeat}s")"
echo -e "${result// /${string}}"
fi
}
नमूना चलता है
$ repeatString 'a1' 10
a1a1a1a1a1a1a1a1a1a1
$ repeatString 'a1' 0
$ repeatString '' 10
संदर्भ लिब पर: https://github.com/gdbtek/linux-cookbooks/blob/master/lbooks/util.bash
मेरा उत्तर थोड़ा अधिक जटिल है, और शायद एकदम सही नहीं है, लेकिन बड़ी संख्या में आउटपुट की तलाश करने वालों के लिए, मैं 3 सेकंड में लगभग 10 मिलियन करने में सक्षम था।
repeatString(){
# argument 1: The string to print
# argument 2: The number of times to print
stringToPrint=$1
length=$2
# Find the largest integer value of x in 2^x=(number of times to repeat) using logarithms
power=`echo "l(${length})/l(2)" | bc -l`
power=`echo "scale=0; ${power}/1" | bc`
# Get the difference between the length and 2^x
diff=`echo "${length} - 2^${power}" | bc`
# Double the string length to the power of x
for i in `seq "${power}"`; do
stringToPrint="${stringToPrint}${stringToPrint}"
done
#Since we know that the string is now at least bigger than half the total, grab however many more we need and add it to the string.
stringToPrint="${stringToPrint}${stringToPrint:0:${diff}}"
echo ${stringToPrint}
}
अधिकांश मौजूदा समाधान सभी {1..10}
शेल के सिंटैक्स समर्थन पर निर्भर करते हैं , जो कि bash
- और zsh
- विशिष्ट है, और tcsh
ओपनबीएसडी ksh
और अधिकांश गैर-बैश में काम नहीं करता है sh
।
निम्नलिखित किसी भी शेल में ओएस एक्स और सभी * बीएसडी सिस्टम पर काम करना चाहिए; वास्तव में, इसका उपयोग विभिन्न प्रकार के सजावटी अंतरिक्ष की एक पूरी मैट्रिक्स उत्पन्न करने के लिए किया जा सकता है:
$ printf '=%.0s' `jot 64` | fold -16
================
================
================
================$
अफसोस की बात है, हम एक अनुगामी newline नहीं मिलता है; जो printf '\n'
गुना के बाद एक अतिरिक्त द्वारा तय किया जा सकता है :
$ printf "=%.0s" `jot 64` | fold -16 ; printf "\n"
================
================
================
================
$
संदर्भ:
मेरा प्रस्ताव ( n के लिए परिवर्तनशील मूल्यों को स्वीकार करते हुए ):
n=100
seq 1 $n | xargs -I {} printf =