बाश में गोल्फ के लिए युक्तियाँ


55

बैश में गोल्फिंग के लिए आपके पास क्या सामान्य सुझाव हैं? मैं उन विचारों की तलाश कर रहा हूं, जो सामान्य तौर पर कम से कम कुछ हद तक बाश के लिए कोड गोल्फ की समस्याओं पर लागू हो सकते हैं (उदाहरण के लिए "टिप्पणियां हटाएं" एक उत्तर नहीं है)। कृपया प्रति उत्तर एक टिप पोस्ट करें।

जवाबों:


36

अप्रतिबंधित , लेकिन विरासत मेंshपीछे की संगतता केलिए मेरे द्वारा चलाए गए हर संस्करण में काम करता है:

forलूप्स आपको { }इसके बजाय उपयोग करने की अनुमति देते हैं do done। जैसे बदलें:

for i in {1..10};do echo $i; done

साथ में:

for i in {1..10};{ echo $i;}

शेल क्या है shऔर यह शेल किस forसिंटैक्स की अनुमति देता है ? इसे स्पष्ट रूप से अनुमति दी गई है zsh
मोकेसर

@ माइकर्स बैश। मुझे याद है कि कहीं न कहीं इस वाक्यविन्यास को पढ़ने की अनुमति थी कि कुछ पुराने shऔर बैश भी इसकी वजह से अनुमति देते हैं, हालांकि दुख की बात यह है कि मेरे पास प्रशस्ति पत्र नहीं है।
डिजिटल ट्रामा

आह ... csh, शायद - कि कैसे वे उस खोल में काम किया है।
mikeserv

वैसे, ksh93उपरोक्त चीज़ में हो सकता है: ;{1..10}और bash:printf %s\\n {1..10}
mikeserv

1
for((;i++<10)){ echo $i;}से कम हैfor i in {1..10};{ echo $i;}
इवान क्राल

29

इसके $[…]बजाय अंकगणितीय विस्तार उपयोग के लिए $((…)):

bash-4.1$ echo $((1+2*3))
7

bash-4.1$ echo $[1+2*3]
7

अंकगणितीय विस्तार में उपयोग नहीं करते हैं $:

bash-4.1$ a=1 b=2 c=3

bash-4.1$ echo $[$a+$b*$c]
7

bash-4.1$ echo $[a+b*c]
7

अंकगणित का विस्तार अनुक्रमित सरणी सदस्यता पर किया जाता है, इसलिए इसका उपयोग $न तो करें:

bash-4.1$ a=(1 2 3) b=2 c=3

bash-4.1$ echo ${a[$c-$b]}
2

bash-4.1$ echo ${a[c-b]}
2

अंकगणितीय विस्तार में उपयोग नहीं करते हैं ${…}:

bash-4.1$ a=(1 2 3)

bash-4.1$ echo $[${a[0]}+${a[1]}*${a[2]}]
7

bash-4.1$ echo $[a[0]+a[1]*a[2]]
7

प्रतिस्थापित करना while((i--)), जो मेरे साथ काम करता है while[i--]या while $[i--]नहीं करता है। जीएनयू बैश, संस्करण 4.3.46 (1)
ग्लेन रैंडर्स-

1
सही है, @ GlennRanders-Pehrson। वह काम करने वाला नहीं है।
9

y=`bc<<<"($x*2.2)%10/1"`... bcगैर-पूर्णांक गणना के लिए उपयोग करने का उदाहरण ... ध्यान दें /1कि अंत में परिणामी दशमलव को एक int में काटता है।
roblogic

s=$((i%2>0?s+x:s+y))... बैश अंकगणित में टर्नरी ऑपरेटर का उपयोग करने का उदाहरण। यह तुलना में कम है if..then..elseया[ ] && ||
roblogic

1
@manatwork धन्यवाद। उन्होंने इसे हटा दिया होगा। मैं चालू हूं GNU bash, version 5.0.2(1)-release (x86_64-apple-darwin16.7.0)और यह मेरा नहीं है।
जोना

19

किसी फ़ंक्शन को परिभाषित करने का सामान्य, लंबा और उबाऊ तरीका है

f(){ CODE;}

जैसा कि इस लड़के को पता चला है, आपको इससे पहले अंतरिक्ष की जरूरत है CODEऔर अर्धविराम के बाद।

यह एक छोटी सी चाल है जो मैंने @DigitalTrauma से सीखी है :

f()(CODE)

यह दो वर्णों वाला है और यह ठीक वैसे ही काम करता है, बशर्ते कि आपको फ़ंक्शन रिटर्न के बाद चर के मूल्यों में किसी भी परिवर्तन को करने की आवश्यकता न हो ( कोष्ठक उप-भाग में शरीर को चलाते हैं )।

जैसा कि @ jimmy23013 टिप्पणियों में बताते हैं, यहां तक ​​कि कोष्ठक भी अनावश्यक हो सकते हैं।

बैश संदर्भ मैनुअल चलता इस प्रकार के रूप में कार्य परिभाषित किया जा सकता है कि:

name () compound-command [ redirections ]

या

function name [()] compound-command [ redirections ]

एक यौगिक आदेश हो सकता है:

  • एक पाशन निर्माण: until, whileयाfor
  • एक सशर्त निर्माण: if, case, ((...))या[[...]]
  • समूहीकृत कमांड: (...)या{...}

इसका मतलब है कि निम्नलिखित सभी मान्य हैं:

$ f()if $1;then $2;fi
$ f()($1&&$2)
$ f()(($1))                # This one lets you assign integer values

और मैं एक चूसने वाले की तरह घुंघराले कोष्ठक का उपयोग कर रहा हूं ...


2
ध्यान दें कि आप उपयोग कर सकते हैं f()while ... f()if ...और अन्य मिश्रित कमांड भी।
jimmy23013

इसने मुझे आश्चर्यचकित किया क्योंकि मुझे लगा कि f()CODEयह कानूनी है। यह पता चला है कि f()echo hipdksh और zsh में कानूनी है, लेकिन बैश में नहीं।
kernigh

1
अपने especiallly उपयोगी w / के forबाद से यह स्थिति के लिए चूक: f()for x do : $x; done;set -x *;PS4=$* f "$@"या कुछ और।
माइकस

16

:एक ऐसा आदेश है जो कुछ भी नहीं करता है, इसकी निकास स्थिति हमेशा सफल होती है, इसलिए इसका उपयोग किया जा सकता है true


एक सबशेल और पाइपिंग का उपयोग करके यह बाइट्स की समान संख्या के बारे में उपयोग करेगा, लेकिन इसे पाइप करना अधिक व्यावहारिक होगा।
ckjbgames

5
सिवाय जब आप करते हैं:(){:|:}
enedil

14

अधिक सुझाव

  1. त्रिगुट ऑपरेटर दुरुपयोग, ((test)) && cmd1 || cmd2या [ test ] && cmd1 || cmd2, जितना संभव हो उतना।

    उदाहरण (लंबाई की गिनती हमेशा शीर्ष पंक्ति को बाहर करती है):

    t="$something"
    if [ $t == "hi" ];then
    cmd1
    cmd2
    elif [ $t == "bye" ];then
    cmd3
    cmd4
    else
    cmd5
    if [ $t == "sup" ];then
    cmd6
    fi
    fi

    केवल टर्नरी ऑपरेटरों का उपयोग करके, इसे आसानी से छोटा किया जा सकता है:

    t="$something"
    [ $t == "hi" ]&&{
    cmd1;cmd2
    }||[ $t == "bye" ]&&{
    cmd3;cmd4
    }||{
    cmd5
    [ $t == "sup" ]&&cmd6
    }

    जैसा कि nyuszika7h ने टिप्पणियों में बताया है, इस विशिष्ट उदाहरण को आगे भी उपयोग करके छोटा किया जा सकता है case:

    t="$something"
    case $t in "hi")cmd1;cmd2;;"bye")cmd3;cmd4;;*)cmd5;[ $t == "sup" ]&&cmd6;esac
  2. इसके अलावा, जहां तक ​​संभव हो ब्रेसिज़ के लिए कोष्ठकों को प्राथमिकता दें। चूंकि कोष्ठक एक मेटाचैकर है, और एक शब्द नहीं है, इसलिए उन्हें कभी भी किसी भी संदर्भ में रिक्त स्थान की आवश्यकता नहीं होती है। यह भी संभव के रूप में एक subshell में के रूप में कई आदेशों को चलाने, क्योंकि घुंघराले ब्रेसिज़ (यानी इसका मतलब है {और }) शब्द, नहीं मेटा-वर्ण आरक्षित हैं, और इस तरह सही ढंग से पार्स करने के लिए दोनों पक्षों पर खाली स्थान के संबंध के लिए है, लेकिन मेटा-वर्ण नहीं है। मुझे लगता है कि आप अब तक जानते हैं कि उपधाराएं मूल वातावरण को प्रभावित नहीं करती हैं, इसलिए यह मानते हुए कि सभी उदाहरण कमांड सुरक्षित रूप से एक उपधारा में चलाए जा सकते हैं (जो किसी भी मामले में विशिष्ट नहीं है), आप उपरोक्त कोड को छोटा कर सकते हैं :

    t=$something
    [ $t == "hi" ]&&(cmd1;cmd2)||[ $t == "bye" ]&&(cmd3;cmd4)||(cmd5;[ $t == "sup" ]&&cmd6)

    इसके अलावा, यदि आप नहीं कर सकते हैं, तो कोष्ठक का उपयोग करना अभी भी कुछ को छोटा कर सकता है। एक बात का ध्यान रखें कि यह केवल पूर्णांकों के लिए काम करता है, जो इस उदाहरण के उद्देश्यों के लिए इसे बेकार कर देता है (लेकिन -eqपूर्णांक के लिए उपयोग करने से बेहतर है )।

  3. एक और बात, जहाँ संभव हो, उद्धरणों से बचें। उस उपरोक्त सलाह का उपयोग करते हुए, आप इसे और छोटा कर सकते हैं। उदाहरण:

    t=$something
    [ $t == hi ]&&(cmd1;cmd2)||[ $t == bye ]&&(cmd3;cmd4)||(cmd5;[ $t == sup ]&&cmd6)
  4. परीक्षण स्थितियों में, एकल ब्रैकेट को कुछ अपवादों के साथ जितना संभव हो सके डबल ब्रैकेट के लिए प्राथमिकता दें। यह दो पात्रों को मुफ्त में छोड़ देता है, लेकिन यह कुछ मामलों में उतना मजबूत नहीं है (यह एक बैश एक्सटेंशन है - उदाहरण के लिए नीचे देखें)। इसके अलावा, डबल के बजाय एकल बराबर तर्क का उपयोग करें। यह एक स्वतंत्र चरित्र है।

    [[ $f == b ]]&&: # ... <-- Bad
    [ $f == b ]&&: # ... <-- Better
    [ $f = b ]&&: # ... <-- Best.  word splits and pathname-expands the contents of $f.  Esp. bad if it starts with -

    इस चेतावनी पर ध्यान दें, विशेष रूप से अशक्त आउटपुट या अपरिभाषित चर के लिए जाँच में:

    [[ $f ]]&&:    # double quotes aren't needed inside [[, which can save chars
    [ "$f" = '' ]&&: <-- This is significantly longer
    [ -n "$f" ]&&:

    सभी तकनीकी में, यह विशिष्ट उदाहरण सबसे अच्छा होगा case... in:

    t=$something
    case $t in hi)cmd1;cmd2;;bye)cmd3;cmd4;;*)cmd5;[ $t == sup ]&&cmd6;esac

तो, इस पोस्ट का नैतिक यह है:

  1. बूलियन ऑपरेटरों का यथासंभव दुरुपयोग करें, और हमेशाif / if-else/ आदि के बजाय उनका उपयोग करें । निर्माण करती है।
  2. कोष्ठकों का यथासंभव उपयोग करें और उप-खण्डों में यथासंभव सेगमेंट चलाएं क्योंकि कोष्ठक मेटा-वर्ण हैं और आरक्षित शब्द नहीं हैं।
  3. यथासंभव शारीरिक रूप से उद्धरण से बचें।
  4. बाहर की जाँच करें case... in, क्योंकि यह काफी कुछ बाइट्स बचा सकता है, विशेष रूप से स्ट्रिंग मिलान में।

पुनश्च: संदर्भ की परवाह किए बिना बैश में मान्यता प्राप्त मेटा-पात्रों की एक सूची यहां दी गई है (और शब्दों को अलग कर सकते हैं):

&lt; &gt; ( ) ; & | &lt;space&gt; &lt;tab&gt;

संपादित करें: जैसा कि मैनटवर्क ने बताया है, डबल कोष्ठक परीक्षण केवल पूर्णांकों के लिए काम करता है। इसके अलावा, अप्रत्यक्ष रूप से, मैंने पाया कि आपको ==ऑपरेटर के आसपास व्हाट्सएप रखने की आवश्यकता है । ऊपर मेरी पोस्ट को ठीक किया।

मैं भी प्रत्येक सेगमेंट की लंबाई पुनर्गणना करने के लिए बहुत आलसी था, इसलिए मैंने उन्हें हटा दिया। यदि आवश्यक हो तो एक स्ट्रिंग लंबाई कैलकुलेटर ऑनलाइन खोजना आसान होना चाहिए।


कहने के लिए क्षमा करें, लेकिन आपकी कुछ गंभीर त्रुटियाँ हैं। [ $t=="hi" ]हमेशा 0 का मूल्यांकन करेगा, क्योंकि इसे पार्स किया गया है [ -n "STRING" ](($t=="hi"))हमेशा 0 का मूल्यांकन करेंगे जब तक कि $ t का गैर-संख्यात्मक मान न हो, क्योंकि अंकगणित मूल्यांकन में स्ट्रिंग को पूर्णांक में मजबूर किया जाता है। कुछ परीक्षण मामले: pastebin.com/WefDzWbL
manatwork 13

@manatwork कैच के लिए धन्यवाद। मैं उसी हिसाब से अपडेट करूंगा।
इशीआ मीडोज

यहाँ का उपयोग करना caseकम होगा। इसके अलावा, आपको पहले स्थान की आवश्यकता नहीं है }, लेकिन आप बाद में करते हैं {
nyuszika7h

1
=से कम मजबूत क्यों होगा ==? =POSIX द्वारा अनिवार्य है, ==नहीं है।
डेनिस

1
प्रश्न प्रति उत्तर एक टिप
मांगता है

7

इसके बजाय grep -E, grep -F, grep -r, उपयोग egrep, fgrep, rgrep, दो वर्ण की बचत। छोटे लोगों को पदावनत किया जाता है, लेकिन वे ठीक काम करते हैं।

(आपने प्रति उत्तर एक टिप मांगी है!)


1
बहुत बुरा वहाँ के लिए कोई नहीं Pgrepहै grep -P। हालांकि मैं देखता हूं कि इसे आसानी से कैसे भ्रमित किया जा सकता है pgrep, जिसका उपयोग प्रक्रियाओं को देखने के लिए किया जाता है।
nyuszika7h

1
@ nyuszika7h मैं व्यक्तिगत रूप से grep -oबहुत उपयोग करता हूं

यह अंतरिक्ष सहित 3 बचा नहीं होगा?
ckjbgames

7

सरणी के तत्व 0 को केवल चर नाम से एक्सेस किया जा सकता है, पाँच बाइट की बचत स्पष्ट रूप से 0 के सूचकांक को निर्दिष्ट करती है:

$ a=(code golf)
$ echo ${a[0]}
code
$ echo $a
code
$ 

7

यदि आपको एक पाइपलाइन में अगली प्रक्रिया के STDIN के लिए चर की सामग्री को पारित करने की आवश्यकता है, तो चर को एक पाइपलाइन में गूंजना आम है। लेकिन आप <<< यहाँ एक बैश के साथ एक ही चीज हासिल कर सकते हैं स्ट्रिंग :

$ s="code golf"
$ echo "$s"|cut -b4-6
e g
$ cut -b4-6<<<"$s"
e g
$ 

2
चूंकि हम गोल्फ कर रहे हैं s=code\ golf, echo $s|और <<<$s(ध्यान में रखते हुए कि बाद के दो काम केवल इसलिए हैं क्योंकि कोई दोहराया स्थान नहीं हैं, आदि)।
डेनिस

6

बचें $( ...command... ), एक विकल्प है जो एक चार बचाता है और एक ही काम करता है:

` ...command... `

9
कभी-कभी $( )ज़रूरत होती है यदि आपके पास कमांड सब्स्टीट्यूट्स हों; अन्यथा आपको ``
डिजिटल ट्रामा

1
ये तकनीकी रूप से अलग-अलग काम करते हैं, मुझे उदाहरण के लिए, $()जब मैं अपनी मशीन पर प्रतिस्थापन को चलाना चाहता था , तो इसके बजाय बैकटिक्स का उपयोग करना पड़ा scp। ज्यादातर मामलों में वे समान हैं।
अंडरग्राउंडोरेल

2
@undergroundmonorail: आपको कभी भी बैकटिक्स की आवश्यकता नहीं है । कुछ भी वे कर सकते हैं, $()अगर आप चीजों को ठीक से उद्धृत कर सकते हैं। (जब तक आपको कुछ ऐसी चीज़ों से बचने के लिए आपकी आज्ञा की आवश्यकता होती है जो मुंगेस $नहीं बल्कि बैकटिक्स होती हैं)। उनके अंदर की चीजों को उद्धृत करने में कुछ सूक्ष्म अंतर हैं। mywiki.wooledge.org/BashFAQ/082 कुछ अंतर बताते हैं। जब तक आप गोल्फ नहीं कर रहे हैं, कभी भी बैकटिक्स का उपयोग न करें।
पीटर कॉर्ड्स

@PeterCordes मुझे यकीन है कि एक रास्ता था, लेकिन उस समय मैंने जो कुछ भी कोशिश की वह काम नहीं की। यहां तक ​​कि अगर बैकटिक्स सबसे अच्छा समाधान नहीं थे, तो मुझे खुशी थी कि मैं उनके बारे में जानता था क्योंकि यह एकमात्र समाधान था जो मेरे पास था। ¯ \ _ (ツ) _ / ¯
भूमिगत

@DigitalTrauma नेस्टिंग का नमूना: echo `bc <<<"\`date +%s\`-12"`... (यह टिप्पणी में backtick युक्त नमूना पोस्ट करने के लिए मुश्किल है, वहाँ;)
एफ। होरी

6

ifसमूह आदेशों का उपयोग करें

इस टिप की तुलना में जो ifबिल्कुल भी हटा देता है , यह केवल कुछ बहुत ही दुर्लभ मामलों में बेहतर काम करना चाहिए, जैसे कि जब आपको वापसी मूल्यों की आवश्यकता होती है if

यदि आपके पास एक कमांड समूह है जो ifकि इस तरह से समाप्त होता है :

a&&{ b;if c;then d;else e;fi;}
a&&(b;if c;then d;else e;fi)

आप ifइसके बजाय आदेशों को शर्त में लपेट सकते हैं :

a&&if b;c;then d;else e;fi

या यदि आपका कार्य समाप्त होता है if:

f(){ a;if b;then c;else d;fi;}

आप ब्रेसिज़ निकाल सकते हैं:

f()if a;b;then c;else d;fi

1
आप [test] && $if_true || $elseइन कार्यों में टर्नरी ऑपरेटर का उपयोग कर सकते हैं और कुछ बाइट्स बचा सकते हैं।
ckjbgames

इसके अलावा, आप के आसपास रिक्त स्थान की जरूरत नहीं है &&और||
रोबेलिक

6

(( ... ))स्थितियों के लिए अंकगणित का उपयोग करें

आप बदल सकते हैं:

if [ $i -gt 5 ] ; then
    echo Do something with i greater than 5
fi

द्वारा

if((i>5));then
    echo Do something with i greater than 5
fi

(नोट: इसके बाद कोई स्थान नहीं है if)

या और भी

((i>5))&&{
    echo Do something with i greater than 5
}

... या यदि केवल एक ही आदेश

((i>5))&&echo Echo or do something with i greater than 5

इसके अलावा: अंकगणितीय निर्माण में चर सेटिंग छिपाएँ:

((i>5?c=1:0))&&echo Nothing relevant there...
# ...
((c))&&echo Doing something else if i was greater than 5

या वही

((c=i>5?c=0,1:0))&&echo Nothing relevant there...
# ...
((c))&&echo Doing something else if i was greater than 5

... जहां अगर मैं> 5, तो c = 1 (0 नहीं;)


के [ ]बजाय का उपयोग करके आप 2 बाइट्स बचा सकता है (())
cjjbgames 15

@ckjbgames क्या आप इसके बारे में सुनिश्चित हैं !? जो आप उपयोग कर रहे हैं संस्करण मार मार ?
एफ। होरी

@Fauri मुझे लगता है कि यह बाइट के संदर्भ में उसी के बारे में होगा।
cjjbgames 15

@ckjbgames [ ]आपको चर के लिए डॉलर चिह्न की आवश्यकता है। मैं नहीं देखता कि कैसे आप एक ही या छोटी लंबाई का उपयोग करके समान कर सकते हैं [ ]
एफ। होरी

बोनस टिप: यदि लूप के लिए पहली पंक्ति शुरू होती है ((...)), तो कोई भी नई रेखा या स्थान आवश्यक नहीं है। जैसे for((;10>n++;)){((n%3))&&echo $n;} ऑनलाइन कोशिश करो!
प्रिमो

6

अनंत छोरों के लिए एक छोटा वाक्यविन्यास (जिसे breakया exitबयानों से बचाया जा सकता है ) है

for((;;)){ code;}

इससे छोटा while true;और है while :;

यदि आपको ज़रूरत नहीं है break( exitभागने के एकमात्र तरीके के साथ ), तो आप इसके बजाय एक पुनरावर्ती फ़ंक्शन का उपयोग कर सकते हैं।

f(){ code;f;};f

यदि आपको ब्रेक की आवश्यकता है, लेकिन आपको बाहर निकलने की आवश्यकता नहीं है और आपको लूप के बाहर किसी भी वैरिएबल मॉडिफिकेशन को करने की आवश्यकता नहीं है, तो आप बॉडी के चारों ओर कोष्ठक के साथ एक पुनरावर्ती कार्य का उपयोग कर सकते हैं , जो फ़ंक्शन बॉडी को एक सबहेल में चलाते हैं।

f()(code;f);f

6

एक-पंक्ति forलूप

सीमा विस्तार के साथ समवर्ती एक अंकगणितीय अभिव्यक्ति का मूल्यांकन सीमा में प्रत्येक आइटम के लिए किया जाएगा। उदाहरण के लिए निम्नलिखित:

: $[expression]{0..9}

expression10 बार मूल्यांकन करेंगे ।

यह अक्सर बराबर forलूप की तुलना में काफी कम होता है :

for((;10>n++;expression with n)){ :;}
: $[expression with ++n]{0..9}

यदि आपको कोई त्रुटि नहीं मिली, तो आप इनबिल्ट को हटा सकते हैं :। 10 से बड़े पुनरावृत्तियों के लिए, आप वर्ण श्रेणियों का उपयोग भी कर सकते हैं, उदाहरण के लिए {A..z}58 बार पुनरावृति करेंगे।

एक व्यावहारिक उदाहरण के रूप में, निम्नलिखित दोनों पहले 50 त्रिकोणीय संख्याओं का उत्पादन करते हैं, प्रत्येक अपनी लाइन पर:

for((;50>d++;)){ echo $[n+=d];} # 31 bytes
printf %d\\n $[n+=++d]{A..r}    # 28 bytes

तुम भी पीछे की ओर पुनरावृति कर सकते हैं:for((;0<i--;)){ f;}
लूट

5

तर्कों पर लूप

के रूप में में नोट एक "foo बार में ..." हिस्सा बिना पाश "के लिए" बैश , in "$@;"में for x in "$@;"अनावश्यक है।

से help for:

for: for NAME [in WORDS ... ] ; do COMMANDS; done
    Execute commands for each member in a list.

    The `for' loop executes a sequence of commands for each member in a
    list of items.  If `in WORDS ...;' is not present, then `in "$@"' is
    assumed.  For each element in WORDS, NAME is set to that element, and
    the COMMANDS are executed.

    Exit Status:
    Returns the status of the last command executed.

उदाहरण के लिए, यदि हम किसी बैश स्क्रिप्ट या किसी फ़ंक्शन के लिए दिए गए सभी तर्कों को स्थितिगत तर्क देना चाहते हैं, तो हम ऐसा कर सकते हैं।

for n;{ echo $[n*n];}

इसे ऑनलाइन आज़माएं!


5

बिल्ली के लिए वैकल्पिक

कहते हैं कि आप किसी फ़ाइल को पढ़ने और उसे किसी और चीज़ में उपयोग करने का प्रयास कर रहे हैं। आप क्या कर सकते हैं:

echo foo `cat bar`

अगर की सामग्री को barथा foobar, इस प्रिंट होगा foo foobar

हालाँकि, यदि आप इस विधि का उपयोग कर रहे हैं, तो एक विकल्प है, जो 3 बाइट्स बचाता है:

echo foo `<bar`

1
क्या कोई कारण है कि <barखुद से काम नहीं करता है, लेकिन इसे बैकटिक्स में रखना पड़ता है?
क्रिकटी लिथोस

@ सहवास हाँ। <एक कमांड के लिए एक फ़ाइल डालता है, लेकिन इस मामले में यह एक मोड़ के कारण मानक आउटपुट में डालता है। बैकटिक्स एक साथ इसका मूल्यांकन करते हैं।
ओकेक्स

क्या इसके अलावा मानक इनपुट से पढ़ने का एक छोटा तरीका है `cat`?
जोएल

4

का प्रयोग करें [बजाय [[और testजब संभव

उदाहरण:

[ -n $x ]


तुलना =के ==लिए उपयोग करें

उदाहरण:

[ $x = y ]

ध्यान दें कि आपके पास बराबर चिह्न के आसपास रिक्त स्थान होना चाहिए या फिर यह काम नहीं करेगा। वही ==मेरे परीक्षणों के आधार पर लागू होता है ।


3
[बनाम [[: आवश्यक उद्धरण की मात्रा पर निर्भर हो सकता है pastebin.com/UPAGWbDQ
manatwork

@manatwork यह एक अच्छी बात है।
nyuszika7h

1
सामान्य नियम: [... ]== /bin/test, लेकिन [[... ]]! = /bin/testऔर एक को कभी भी पसंद नहीं करना चाहिए [... ]ओवर [[... ]]कोडगॉल्फ के बाहर
बिल्ली

4

के लिए विकल्प head

lineतीन बाइट्स से कम है head -1, लेकिन पदावनत किया जा रहा है ।

sed qदो बाइट्स से छोटा है head -1

sed 9qएक बाइट से छोटा है head -9


1
हालांकि बर्बाद , हम अभी भी एक लाइन पढ़ने के लिए उपयोग -लिनक्स पैकेज lineसे थोड़ी देर के लिए उपयोग कर सकते हैं ।
मैनटवर्क

4

tr -cd से छोटा है grep -o

उदाहरण के लिए, यदि आपको रिक्त स्थान की गणना करने की आवश्यकता है, grep -o <char>(केवल मिलान किए गए प्रिंट करें) 10 बाइट्स देता है जबकि tr -cd <char>(पूरक हटाएं <char>) 9 देता है।

# 16 bytes
grep -o \ |wc -l
# 15 bytes
tr -cd \ |wc -c

( स्रोत )

ध्यान दें कि वे दोनों थोड़ा अलग आउटपुट देते हैं। grep -oरिटर्न लाइन अलग-अलग परिणाम देते हुए tr -cdउन्हें एक ही लाइन पर देती है, इसलिए trहमेशा अनुकूल नहीं हो सकती है।


4

फ़ाइल नाम छोटा करें

हाल ही में एक चुनौती में मैं फ़ाइल को पढ़ने की कोशिश कर रहा था /sys/class/power_supply/BAT1/capacity, हालांकि इसे छोटा किया जा सकता है /*/*/*/*/capac*yक्योंकि उस प्रारूप में कोई अन्य फाइल मौजूद नहीं है।

उदाहरण के लिए, यदि आपके पास एक निर्देशिका थी foo/जिसमें फाइलें थीं foo, bar, foobar, barfooऔर आप फाइल को संदर्भित करना चाहते थे foo/barfoo, तो आप foo/barf*एक बाइट को बचाने के लिए उपयोग कर सकते हैं ।

*"कुछ भी" का प्रतिनिधित्व करता है, और रेगेक्स के बराबर है .*


3

:कमांड के बजाय एक पाइप का उपयोग करें /dev/null:में निर्मित अपने सभी इनपुट खाएंगे।


2
नहीं, यह ज्यादातर मामलों में SIGPIPE के साथ प्रोग्राम को क्रैश कर देगा। echo a|tee /dev/stderr|:कुछ भी नहीं छापेंगे।
jimmy23013

एक दौड़ है: echo a|tee /dev/stderr|:मेरे कंप्यूटर पर प्रिंट किया, लेकिन कहीं और SIGPIPE पहले टी को मार सकता है। यह संस्करण पर निर्भर हो सकता है tee
kernigh

हां, यह एक बड़ी समस्या है: tee >(:) < <(seq 1 10)काम करेगा, लेकिन tee /dev/stderr | :नहीं करेगा। यहां तक ​​कि a() { :;};tee /dev/stderr < <(seq 1 10)| aकुछ भी प्रिंट नहीं।
एफ। हौरी

@ user16402 - आपके पास मेरे नाम के लिए एक फ़ेकिंग नाम होना चाहिए ... वैसे भी, :आंतरिक बिल्कुल नहीं खाता है ... यदि आप कोलन के इनपुट का उपयोग करते हैं तो आप एक पाइप को बाढ़ से बाहर कर सकते हैं ... लेकिन आप एक रीडायरेक्ट कर सकते हैं एक बृहदान्त्र द्वारा, या इसके साथ एक प्रक्रिया को छोड़ दें ... :| while i>&$(($??!$?:${#?})) command shit; do [ -s testitsoutput ]; doneया फिर भी कि छद्म सुझाव लागू होता है ... भी, क्या आप जानते हैं कि आप मेरे बारे में इतने भयावह हैं? ... सब पर से बचने की लागत< <(psycho shit i can alias to crazy math eat your world; okay? anyway, ksh93 has a separate but equal composite char placement)
mikeserv

3

splitएक और (पदावनत, लेकिन किसी को परवाह नहीं है) Nप्रत्येक के लिए लाइनों के वर्गों में इनपुट विभाजन के लिए वाक्यविन्यास : इसके बजाय split -lNआप split -Nउदाहरण के लिए उपयोग कर सकते हैं split -9


3

परीक्षणों का विस्तार करें

अनिवार्य रूप से, शेल एक प्रकार की मैक्रो भाषा है, या कम से कम एक संकर या कुछ प्रकार है। प्रत्येक कमांड-लाइन को मूल रूप से दो भागों में विभाजित किया जा सकता है: पार्सिंग / इनपुट भाग और विस्तार / आउटपुट भाग।

पहला भाग वह है जिस पर अधिकांश लोग ध्यान केंद्रित करते हैं क्योंकि यह सबसे सरल है: आप देखते हैं कि आपको क्या मिलता है। दूसरा भाग वह है जो कई लोग कभी भी बहुत अच्छी तरह से समझने की कोशिश करने से बचते हैं और इसीलिए लोग कहते हैं कि जैसी चीजें evalबुराई हैं और हमेशा आपके विस्तार को उद्धृत करती हैं - लोग चाहते हैं कि पहले भाग का परिणाम पहले के बराबर हो। यह ठीक है - लेकिन यह अनावश्यक रूप से लंबे कोड शाखाओं और असंगत परीक्षण के टन की ओर जाता है।

विस्तार स्व-परीक्षण है${param[[:]#%+-=?]word}रूपों पर्याप्त एक पैरामीटर की सामग्री को मान्य करने के लिए की तुलना में अधिक कर रहे हैं, nestable हैं, और सभी के लिए के मूल्यांकन के आसपास आधारित हैं NUL - है जो ज्यादातर लोगों परीक्षणों के वैसे भी उम्मीद है। +विशेष रूप से छोरों में काम कर सकते हैं:

r()while IFS= read -r r&&"${r:+set}" -- "$@" "${r:=$*}";do :;done 2>&-

IFS=x
printf %s\\n some lines\ of input here '' some more|{ r;echo "$r"; }

somexlines ofxinputxhere

... जबकि readखाली लाइनों में "${r:+set}"विस्तार नहीं होता है "set"और स्थितियाँ $rजुड़ जाती हैं। लेकिन जब एक खाली लाइन होती है read, $rखाली होती है और उसका "${r:+set}"विस्तार होता है ""- जो एक अमान्य कमांड है। लेकिन क्योंकि कमांड लाइन का विस्तार किया गया है इससे पहले कि"" अशक्त आदेश की खोज की है, "${r:=$*}"positionals में पहली बाइट पर concatenated के सभी मानों का उपयोग $IFSके रूप में अच्छी तरह से। कंपाउंड कमांड w / r()फिर अगले इनपुट पैराग्राफ को प्राप्त करने के लिए एक अलग मूल्य के रूप में फिर से बुलाया जा सकता है , क्योंकि यह इनपुट में अगली ईवालाइन से परे बफर के लिए एक शेल के लिए अवैध है ।|{;}$IFSread\n


3

छोरों को छोटा करने के लिए पूंछ की पुनरावृत्ति का उपयोग करें:

ये व्यवहार में समतुल्य हैं (हालाँकि संभवतः मेमोरी / पीआईडी ​​उपयोग में नहीं):

while :;do body; done
f()(body;f);f
body;exec $0
body;$0

और ये लगभग बराबर हैं:

while condition; do body; done
f()(body;condition&&f);f
body;condition&&exec $0
body;condition&&$0

(तकनीकी रूप से अंतिम तीन हमेशा शरीर को कम से कम एक बार निष्पादित करेंगे)

उपयोग करने के $0लिए आपकी स्क्रिप्ट को फ़ाइल में होना आवश्यक है, बैश प्रॉम्प्ट में चिपकाया नहीं गया।

अंततः आपका स्टैक ओवरफ्लो हो सकता है, लेकिन आप कुछ बाइट्स बचाते हैं।


3

कभी-कभी exprसामान्य के बजाय एक साधारण अंकगणितीय अभिव्यक्ति के परिणाम को प्रदर्शित करने के लिए बिलिन का उपयोग करना कम होता है echo $[ ]। उदाहरण के लिए:

expr $1 % 2

एक बाइट से छोटी है:

echo $[$1%2]

2

आउटपुट की एक लाइन उत्पन्न करने के pwdबजाय उपयोग करेंecho

स्टडआउट पर एक लाइन लगाने की आवश्यकता है, लेकिन सामग्री के बारे में परवाह नहीं है, और शेल बिल्डिंग्स के लिए अपने उत्तर को प्रतिबंधित करना चाहते हैं? pwdसे एक बाइट कम है echo


2

स्ट्रिंग को प्रिंट करते समय उद्धरण छोड़ा जा सकता है।

echo "example"
echo example

SM-T335 LTE, Android 5.1.1 में आउटपुट:

u0_a177@milletlte:/ $ echo "example"
example
u0_a177@milletlte:/ $ echo example
example

2

जब आप नॉनकॉन्टिनेंट सरणी आइटम असाइन करते हैं, तब भी आप निरंतर विखंडू के क्रमिक सूचकांक को छोड़ सकते हैं:

bash-4.4$ a=([1]=1 [2]=2 [3]=3 [21]=1 [22]=2 [23]=3 [31]=1)

bash-4.4$ b=([1]=1 2 3 [21]=1 2 3 [31]=1)

नतीजा वही है:

bash-4.4$ declare -p a b
declare -a a=([1]="1" [2]="2" [3]="3" [21]="1" [22]="2" [23]="3" [31]="1")
declare -a b=([1]="1" [2]="2" [3]="3" [21]="1" [22]="2" [23]="3" [31]="1")

के अनुसार man bash:

Arrays फ़ॉर्म नाम = (मान 1 ... मान n ) के यौगिक असाइनमेंट का उपयोग करने के लिए असाइन किए गए हैं , जहां प्रत्येक मान फॉर्म [ सबस्क्रिप्ट ] = स्ट्रिंग का है । अनुक्रमित सरणी असाइनमेंट में स्ट्रिंग के अलावा कुछ भी आवश्यकता नहीं है । अनुक्रमित सरणियों को असाइन करते समय, यदि वैकल्पिक ब्रैकेट और सबस्क्रिप्ट की आपूर्ति की जाती है, तो उस सूचकांक को सौंपा जाता है; अन्यथा असाइन किए गए तत्व का सूचकांक, स्टेटमेंट प्लस द्वारा निर्दिष्ट अंतिम इंडेक्स है।


जोड़ने में मददगार: अनैतिक तत्वों का विस्तार अंकगणितीय विस्तार में 0 और अन्य विस्तार में "" होगा।
डिजिटल ट्रॉमा

2

पहले शब्द को एक स्ट्रिंग में प्रिंट करें

यदि स्ट्रिंग चर में है aऔर इसमें एस्केप और प्रारूप वर्ण ( \और %) नहीं हैं, तो इसका उपयोग करें:

printf $a

यदि मुद्रण के बजाय परिणाम को एक चर में सहेजना आवश्यक है, तो यह निम्नलिखित कोड से अधिक लंबा होगा:

x=($a)
$x

1

1 forनिर्देश के साथ 2 एम्बेडिंग लूप करें:

for ((l=i=0;l<=99;i=i>98?l++,0:++i)) ;do
    printf "I: %2d, L: %2d\n" $i $l
done |
    tee >(wc) | (head -n4;echo ...;tail -n 5)
I:  0, L:  0
I:  1, L:  0
I:  2, L:  0
I:  3, L:  0
...
I: 96, L: 99
I: 97, L: 99
I: 98, L: 99
I: 99, L: 99
  10000   40000  130000

1

असाइन और प्रिंट उद्धृत तार

यदि आप किसी चर के लिए एक उद्धृत स्ट्रिंग निर्दिष्ट करना चाहते हैं, और फिर उस चर के मूल्य को प्रिंट करते हैं, तो ऐसा करने का सामान्य तरीका होगा:

a="Programming Puzzles & Code Golf";echo $a

अगर aपहले से परेशान था, तो इसे छोटा किया जा सकता है:

echo ${a=Programming Puzzles & Code Golf}

यदि aपहले सेट किया गया था, तो इसके बजाय इसका उपयोग किया जाना चाहिए:

echo ${a+Programming Puzzles & Code Golf}

ध्यान दें कि यह केवल तभी उपयोगी है जब स्ट्रिंग को उद्धरण की आवश्यकता होती है (उदाहरण में व्हॉट्सएप होता है)। उद्धरण के बिना, a=123;echo $aबस के रूप में छोटा है।


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