एक लाइन में हर शब्द को दोहराने के लिए बैश स्क्रिप्ट?


13

मेरे पास एक स्ट्रिंग है जैसे: dog cat bird whale

और मैं पाना चाहता हूं dog dog cat cat bird bird whale whale

सभी शब्द एक ही पंक्ति में हैं। कोई उपाय?

जवाबों:


28

समाधान के परिवार में जोड़ना :-)।

duplicator.sh:

for i; do echo -n "$i $i "; done; echo

निष्पादन योग्य बनाएं, और अब:

$ ./duplicator.sh dog cat bird whale
dog dog cat cat bird bird whale whale

वैकल्पिक रूप से एक शेल फ़ंक्शन के लिए, उदाहरण के लिए एक स्क्रिप्ट के भीतर पुन: प्रयोज्य होना:

duplicator() {
    for i; do echo -n "$i $i "; done; echo
}

जो तब सीधे चलाए जा सकते हैं जहां परिभाषित किया गया है

duplicator dog cat bird whale

4
मुझे शेल दृष्टिकोण की सादगी पसंद है।
हेंक लैंगवेल्ड

वैसे मैं वास्तव में इस समाधान की सादगी से प्यार करता हूं
क्रिस्टियन

मैंने जिन तरीकों के बारे में सोचा, उनमें से पहले कुछ से बेहतर था।
जो

21

आप उपयोग कर सकते हैं sed:

sed -r 's/(\S+)/\1 \1/g' filename

यदि आप फ़ाइल में किए गए परिवर्तनों को इन-प्लेस में सहेजना चाहते हैं, तो कहें:

sed -i -r 's/(\S+)/\1 \1/g' filename

आप यह भी उपयोग कर सकते हैं perl:

perl -M5.10.0 -ne 'say join " ", map{$_, $_} split " ";' filename

( -iफ़ाइल में किए गए परिवर्तनों को सहेजने के लिए विकल्प जोड़ें ।)

या, टेर्डन द्वारा सुझाए गए अनुसार :

perl -M5.10.0 -ane 'say join " ", map{$_, $_} @F;' filename

से उद्धृत perlvar:

@F

सरणी @Fमें प्रत्येक पंक्ति के फ़ील्ड शामिल हैं, जब ऑटोसप्लिट मोड चालू होता है। -aस्विच के लिए perlrun देखें । यह सरणी पैकेज-विशिष्ट है, और घोषित होने पर पैकेज मुख्य में नहीं होने पर पूर्ण पैकेज नाम घोषित या दिया जाना चाहिए strict 'vars'


4
छोटा: sed -r 's/\S+/& &/g'
18

2
वह बैश स्क्रिप्ट नहीं है। कुछ कमांड (यहां तक ​​कि एक बैश शेल से) को शामिल करने पर एक बैश स्क्रिप्ट शामिल नहीं होती है।
पीटर मोर्टेंसन

4
@PeterMortensen आप तकनीकी रूप से सही हैं (सबसे अच्छा प्रकार का सही), लेकिन व्यावहारिक रूप से हर सिस्टम जिसमें बैश स्थापित है, उसमें मानक यूनिक्स उपकरण भी होंगे, जिनमें सेड और ऑक शामिल हैं। शेल स्क्रिप्टिंग का पूरा बिंदु (अच्छी तरह से, इसके बिंदु का एक बड़ा हिस्सा) सही स्थान पर कमांड इंगित करना है।
evilsoup

3
@PeterMortensen यह गलत है। एक बैश स्क्रिप्ट बाहरी आदेशों को कॉल कर सकती है। बैश स्क्रिप्ट को एक शेबंग लाइन से शुरू करना चाहिए, लेकिन यह कड़ाई से आवश्यक नहीं है। यह प्रश्न निर्दिष्ट नहीं करता है कि बैश स्क्रिप्ट को बाहरी कमांड नहीं कहा जाना चाहिए (जिसे अक्सर "शुद्ध बैश स्क्रिप्ट" कहा जाता है)।
गिलेस एसओ- बुराई को रोकना '

2
अच्छा पर्ल ट्रिक। आप इसे इसके साथ छोटा कर सकते हैं -a:perl -M5.10.0 -ane 'say join " ", map{$_, $_} @F;'
terdon

4

यह एक awk/gawkउत्तर के बिना क्या होगा :

$ awk '{ for(i=1;i<=NF+1;i+=1/2) { printf("%s ",$i); }}' <<<"dog cat bird whale"
dog dog cat cat bird bird whale whale 

यदि एक समाप्ति न्यूलाइन महत्वपूर्ण है:

$ awk '{ for(i=1;i<=NF+1;i+=1/2) { printf("%s ",$i); }} END{print ""}' <<<"dog cat bird whale"

मेरा फर्स्ट डाउन। बस जिज्ञासु, क्यों? क्या स्क्रिप्ट में कुछ गड़बड़ है? या अधिक संक्षिप्त संस्करण?
user19087

मेरे डाउनवोट नहीं, बल्कि for(i=1;i<=NF;++i) printf "%s %s ",$i,$i;छोटे और अधिक पठनीय, IMHO दोनों हैं।
रिची

उस के साथ बहस करने के लिए मुश्किल है, इसलिए मैंने अपना उत्तर सरल कर दिया है और दृष्टिकोण में बदलाव किए बिना (अब किलों में नीचे की ओर राउंड किए जा रहे सूचकांकों का लाभ उठाता है)। उम्मीद है कि अब यह स्पष्ट है।
user19087

1
वह बैश स्क्रिप्ट नहीं है। कुछ कमांड (यहां तक ​​कि एक बैश शेल से) को शामिल करने पर एक बैश स्क्रिप्ट शामिल नहीं होती है।
पीटर मोर्टेंसन

यह एक स्क्रिप्ट में लाना तुच्छ है, यद्यपि।
केविन

3
s="dog cat bird wale"
ss=$( tr ' ' '\n' <<< "$s" | sed p | tr '\n' ' ' )
echo "$ss"
dog dog cat cat bird bird wale wale 

1
मैंने लिखने के बारे में सोचा sed -n 'p;p'- मैंने सोचा कि यह क्या कर रहा है, इसके बारे में अधिक पारदर्शी था।
ग्लेन जैकमैन

1
आपको उसे उत्तर में जोड़ना चाहिए!
टेराडॉन

1

यदि आपके पास एक चर में अपनी स्ट्रिंग है, तो कहें foo="dog cat bird whale", आप कर सकते हैं:

  • शुद्ध बैश:

    $ echo "$foo" | (read a b c d && echo "$a $a $b $b $c $c $d $d")
    dog dog cat cat bird bird whale whale

    स्पष्टीकरण: कोष्ठकों ताकि जरूरत है readऔर echoएक ही subshell में होती हैं और इसलिए शेयर चर कर सकते हैं। उनके बिना, echoबस एक रिक्त रेखा मुद्रित होगी।

  • coreutils:

    $ join -j 5 -o 1.1,1.1,1.2,1.2,1.3,1.3,1.4,1.4 <(echo $foo) <(echo)
    dog dog cat cat bird bird whale whale

    स्पष्टीकरण:-o का झंडा joinआप उत्पादन प्रारूप निर्धारित करने की अनुमति देता है। यहां, मैं इसे पहली फ़ाइल के 1 क्षेत्र ( 1.1) को प्रिंट करने के लिए कह रहा हूं , इसके बाद 1 फाइल के 2 क्षेत्र ( 1.2) आदि। इस तरह 1 फाइल के प्रत्येक क्षेत्र को दो बार प्रिंट किया जाता है। हालांकि, एक सामान्य क्षेत्र पर दो इनपुट लाइनों में joinशामिल होने के लिए, अच्छी तरह से डिज़ाइन किया गया है । इसलिए, मैं इसे एक रिक्त पंक्ति ( ) भी पास करता हूं और फिर इसे अनदेखा करता हूं । सेट क्षेत्र में शामिल होने, एक है कि अस्तित्व में नहीं है (5 वीं) के लिए यह स्थापित करने का कारण बनता है पूरी पंक्ति मुद्रित करने के लिए।<(echo)-jjoin

    अगर आपको व्हाट्सएप या इनपुट ऑर्डर की परवाह नहीं है, तो आप कर सकते हैं

    $ paste <(echo $foo) <(echo $foo)
    dog cat bird wale   dog cat bird wale
  • पर्ल 1:

    $ echo $foo | perl -lane 'push @k, $_,$_ for @F; print "@k"'
    dog dog cat cat bird bird whale whale

    स्पष्टीकरण:

    -l: adds a newline to each print call (among other things)
    -a: turns on field splitting, fields are saved as @F
    -n: process input line by line
    -e: give a script as a command line parameter.

    ऊपर दी गई स्क्रिप्ट प्रत्येक फ़ील्ड ( @Fदो बार) को सरणी में सहेजेगी @kऔर फिर प्रिंट करेगी @k। यदि आपको अनुगामी न्यूलाइन की आवश्यकता नहीं है, तो आप इसे सरल बना सकते हैं

    $ echo $foo | perl -ane 'print " $_ $_" for @F'
  • पर्ल 2:

    $ echo $foo | perl -0040 -pne 'print "$_"' | paste - - 
    dog dog cat cat bird bird whale whale

    स्पष्टीकरण:-0 विकल्प इनपुट रिकॉर्ड विभाजक सेट (हेक्साडेसिमल या ऑक्टल संख्या के रूप में, देखने के लिए यहाँ रूपांतरणों के लिए)। यहां, मैं इसे ऑक्टल पर सेट कर रहा हूं 040जो एक स्थान है। -pबनाता है perlप्रत्येक इनपुट "पंक्ति" प्रिंट और के बाद से हम अंतरिक्ष के लिए रिकॉर्ड विभाजक निर्धारित किया है, लाइनों अब रिक्त स्थान से है, इसलिए हर क्षेत्र में दो बार छपा है परिभाषित कर रहे हैं।

  • awk:

    $ echo $foo | awk '{for(i=1;i<=NF;i++){$i=$i" "$i;} 1;}'
    dog dog cat cat bird bird whale whale

    स्पष्टीकरण: NF फ़ील्ड की संख्या है, इसलिए ऊपर की स्क्रिप्ट प्रत्येक फ़ील्ड के माध्यम से जाती है और इसे अपने आप में जोड़ देती है। एक बार ऐसा हो जाने के बाद, हम लाइन प्रिंट करते हैं ( 1;प्रिंट के लिए सिर्फ शॉर्टहैंड है)।


0

अब एक pythonजवाब के लिए:

कमांड लाइन से:

$ python -c "import sys; s=sys.argv[1:]; print(' '.join(j for i in zip(s,s)for j in i));" dog cat bird whale

स्टडिन से:

$ python -c "s=input().split(); print(' '.join(j for i in zip(s,s)for j in i));" <<<"dog cat bird whale"

दोनों मामलों में परिणाम:

dog dog cat cat bird bird whale whale

0

थोड़ा-सा ओवर-द-टॉप, लेकिन एक haskellजवाब:

$ ghc -e "getLine >>= putStrLn . unwords . (concatMap $ replicate 2) . words" <<<"dog cat bird whale"
dog dog cat cat bird bird whale whale

0

एक अन्य दृष्टिकोण, केवल बैश बिल्डरों का उपयोग करना

$ string="dog cat bird whale"
$ twix() { while [[ ! -z $1 ]]; do printf "%s %s " $1 $1; shift; done; }
$ twix $string
dog dog cat cat bird bird whale whale

मुझे शीर्ष उत्तर की तुलना में कोई लाभ नहीं दिखता है, बस थोड़ा अलग तरीके से दिखाने के लिए, जो कुछ उद्देश्यों के लिए बेहतर हो सकता है।


echoबैश (परीक्षण type echo) में निर्मित एक शेल भी है ।
डैनियल एंडरसन

@DanielAndersson: बिल्कुल, इसलिए मैंने लिखा " भी केवल बैश builtins का उपयोग कर", अपने अच्छे होने (पहले से ही +1 किए गए) को ध्यान में जवाब।
खपरैल

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