कैसे जागता है '' [एक [$ 0] ++ 'काम?


40

यह एक-लाइनर पाठ इनपुट से पूर्व-छँटाई के बिना डुप्लिकेट लाइनों को हटा देता है।

उदाहरण के लिए:

$ cat >f
q
w
e
w
r
$ awk '!a[$0]++' <f
q
w
e
r
$ 

मूल कोड जो मैंने इंटर्नेट पर पढ़ा है:

awk '!_[$0]++'

यह मेरे लिए और भी अधिक हैरान करने वाला था क्योंकि मैंने _पर्ल में जैसे कि जाग में एक विशेष अर्थ लिया था, लेकिन यह एक सरणी का सिर्फ एक नाम था।

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

मैं क्या सीखना चाहूंगा कि इस धारणा की व्याख्या कैसे होती है। जैसे कि बैंग साइन ( !) का मतलब क्या है और इस कोड के अन्य तत्व स्निपेट हैं।

यह कैसे काम करता है?


शीर्षक भ्रामक है, यह $ 0 (शून्य) होना चाहिए, न कि $ o (ओ)।
आर्केमेयर

2
जैसा कि यह एक हैश है, यह अनियंत्रित है, इसलिए "आगमन के क्रम में" वास्तव में सही नहीं है।
केविन

जवाबों:


35

चलो देखते हैं,

 !a[$0]++

प्रथम

 a[$0]

हम a[$0]( aसंपूर्ण इनपुट लाइन के साथ सरणी $0) के मान को देखते हैं ।

यदि यह मौजूद नहीं है ( !परीक्षण में निषेध सत्य के रूप में स्पष्ट होगा)

 !a[$0]

हम इनपुट लाइन $0(डिफ़ॉल्ट क्रिया) प्रिंट करते हैं ।

इसके अलावा, हम एक ( ++) को जोड़ते हैं a[$0], इसलिए अगली बार !a[$0]झूठी का मूल्यांकन करेंगे।

अच्छा लगा, ढूंढो !! आपको कोड गोल्फ पर एक नज़र रखना चाहिए!


1
तो सार यह है: एकल उद्धरण में अभिव्यक्ति awkप्रत्येक इनपुट लाइन के लिए एक परीक्षण के रूप में उपयोग किया जाता है; हर बार परीक्षण सफल awkहोने पर कर्ली ब्रेसिज़ में कार्रवाई को अंजाम देता है, जो कि जब छोड़ा जाता है {print}। धन्यवाद!
अलेक्जेंडर शेकब्लिकिन

3
@Archemar: यह जवाब गलत है, देखिए मेरा।
congonglm

@AlexanderShcheblikin में awk, डिफ़ॉल्ट क्रिया है {print $0}। इसका मतलब यह है कि कुछ भी सच के रूप में मूल्यांकन यह डिफ़ॉल्ट रूप से निष्पादित करेगा। इसलिए उदाहरण के लिए awk '1' fileसभी लाइनों को awk '$1' fileप्रिंट करता है, उन सभी लाइनों को प्रिंट करता है जिनका पहला क्षेत्र खाली नहीं है या 0, आदि
फेडोरक्वि

6
@Gnouc मुझे इस उत्तर में कोई गंभीर त्रुटि दिखाई नहीं देती है। यदि ऐसा है जिसका आप उल्लेख कर रहे हैं, तो अभिव्यक्ति के मूल्य की गणना के बाद वेतन वृद्धि लागू होती है। यह सच है कि इंक्रीमेंट प्रिंटिंग से पहले होता है, लेकिन यह मामूली खराबी है, जो मूल स्पष्टीकरण को प्रभावित नहीं करता है।
गिल्स एसओ- बुराई को रोकना '

1
मुझे नौसिखिया समझने के लिए सबसे अच्छा स्पष्टीकरण मिला यहाँ quora: qr.ae/TUIVxM
GP92

30

यहाँ प्रसंस्करण है:

  • a[$0]: $0साहचर्य सरणी में कुंजी के मूल्य को देखें a। यदि यह मौजूद नहीं है, तो इसे बनाएं।

  • a[$0]++: के मूल्य में वृद्धि a[$0], अभिव्यक्ति के मूल्य के रूप में पुराने मूल्य को लौटाएं। तो a[$0], मौजूद नहीं है वापसी 0और वेतन वृद्धि a[$0]के लिए 1( ++ऑपरेटर रिटर्न संख्यात्मक मान)।

  • !a[$0]++: अभिव्यक्ति के मूल्य को नकारना। यदि a[$0]++लौटाया जाता है 0, तो पूरी अभिव्यक्ति का मूल्यांकन सही होता है, awkप्रदर्शन की गई डिफ़ॉल्ट कार्रवाई करें print $0। अन्यथा, संपूर्ण अभिव्यक्ति का मूल्यांकन असत्य से किया जाता है, इसके कारण awkकुछ भी नहीं होते हैं।

संदर्भ:

साथ gawkमें, हम उपयोग कर सकते हैं dgawk (या awk --debugनए संस्करण के साथ) एक डिबग करने के लिए gawkस्क्रिप्ट। सबसे पहले, एक gawkस्क्रिप्ट बनाएं , जिसका नाम test.awk:

BEGIN {                                                                         
    a = 0;                                                                      
    !a++;                                                                       
}

तो भागो:

dgawk -f test.awk

या:

gawk --debug -f test.awk

डीबगर कंसोल में:

$ dgawk -f test.awk
dgawk> trace on
dgawk> watch a
Watchpoint 1: a
dgawk> run
Starting program: 
[     1:0x7fe59154cfe0] Op_rule             : [in_rule = BEGIN] [source_file = test.awk]
[     2:0x7fe59154bf80] Op_push_i           : 0 [PERM|NUMCUR|NUMBER]
[     2:0x7fe59154bf20] Op_store_var        : a [do_reference = FALSE]
[     3:0x7fe59154bf60] Op_push_lhs         : a [do_reference = TRUE]
Stopping in BEGIN ...
Watchpoint 1: a
  Old value: untyped variable
  New value: 0
main() at `test.awk':3
3           !a++;
dgawk> step
[     3:0x7fe59154bfc0] Op_postincrement    : 
[     3:0x7fe59154bf40] Op_not              : 
Watchpoint 1: a
  Old value: 0
  New value: 1
main() at `test.awk':3
3           !a++;
dgawk>

आप देख सकते हैं, Op_postincrementपहले निष्पादित किया गया था Op_not

आप इसका उपयोग siया stepiइसके बजाय sया stepअधिक स्पष्ट रूप से देखने के लिए कर सकते हैं:

dgawk> si
[     3:0x7ff061ac1fc0] Op_postincrement    : 
3           !a++;
dgawk> si
[     3:0x7ff061ac1f40] Op_not              : 
Watchpoint 1: a
  Old value: 0
  New value: 1
main() at `test.awk':3
3           !a++;

3
@Archemar: आपका उत्तर इंगित करता है कि !पहले लागू किया गया है ++
cuonglm

6
यह उत्तर गलत है। !संचालक के परिणाम की गणना के बाद वृद्धि होती है। आप ऑपरेटर पूर्वता (भ्रमित कर रहे हैं !a[$0]++की तरह पार्स किया गया है !(a[$0]++)मूल्यांकन के आदेश के साथ) (नया मान का का काम a[$0]अभिव्यक्ति के मूल्य के बाद क्या होता गणना की गई है)।
गिल्स एसओ- बुराई को रोकना '

5
@Gnouc यह आपके द्वारा बताए गए मार्ग में सही कहता है, और यदि यह आपके द्वारा बताए गए तरीके से काम करता है, तो इस कोड का वांछित प्रभाव नहीं होगा। पहले मूल्य !xकी गणना की जाती है, जहां xका पुराना मूल्य है a[$0]। फिर a[$0]सेट किया जाता है 1+x
गिल्स एसओ- बुराई को रोकना '

7
मेरा मानना ​​है कि जो जागता है उसका आपका विश्लेषण सही है। क्षमा करें यदि मैं कल अन्यथा निहित हूं। हालाँकि, अर्चेमर के उत्तर की आपकी आलोचना गलत है। आर्केमर पूर्ववर्तीता की गलतफहमी नहीं करता है, आप करते हैं, आप मूल्यांकन के क्रम के साथ पूर्वता को भ्रमित कर रहे हैं (मेरी पिछली टिप्पणी देखें)। यदि आप में आर्चेमार के उत्तर का कोई उल्लेख हटाते हैं, तो आपका उत्तर सही होना चाहिए। जैसा कि यह है, यह आर्कमेकर को गलत साबित करने पर केंद्रित है, और यह मामला नहीं है।
गिलेस एसओ-

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