NR और FNR क्या हैं और “NR == FNR” का क्या अर्थ है?


85

मैं का उपयोग कर फ़ाइल तुलना सीख रहा हूँ awk

मुझे नीचे जैसा सिंटैक्स मिला,

awk 'NR==FNR{a[$1];next}$1 in a{print $1}' file1 file2

मैं समझ नहीं पा रहा था कि इसमें क्या महत्व है NR==FNR? अगर मैं कोशिश करता हूं FNR==NRतो मुझे भी वही आउटपुट मिलता है?

यह वास्तव में क्या करता है?


20
आप अगर आश्चर्यचकित हो सकते हैं a==bऔर b==aएक ही परिणाम का उत्पादन किया?
एड मॉर्टन

5
Backreference.org/2010/02/10/idiomatic-awkTwo-file Processing पर देखें
Etan Reisner

जवाबों:


93

Awk FNRमें, वर्तमान फ़ाइल में रिकॉर्ड संख्या (आमतौर पर लाइन नंबर) को NRसंदर्भित करता है और कुल रिकॉर्ड संख्या को संदर्भित करता है। ऑपरेटर ==एक तुलना ऑपरेटर है, जो दो आसपास के ऑपरेशंस के बराबर होने पर वापस लौटता है।

इसका मतलब है कि शर्त NR==FNR केवल पहली फ़ाइल के लिए सही है, क्योंकि FNRप्रत्येक फ़ाइल की पहली पंक्ति के लिए 1 पर रीसेट होती है , लेकिन NRबढ़ती रहती है।

इस पैटर्न का उपयोग आम तौर पर केवल पहली फ़ाइल पर कार्रवाई करने के लिए किया जाता है। nextब्लॉक साधन किसी भी आगे आदेशों, को छोड़ दिया जाता है ताकि वे केवल पहले की तुलना में अन्य फ़ाइलों पर चलाए जा रहे हैं अंदर।

हालत के FNR==NRरूप में एक ही दो ऑपरेंड की तुलना करता है NR==FNR, इसलिए यह उसी तरह से व्यवहार करता है।


3
"=" कभी-कभी समानता का परीक्षण करने के लिए और कभी-कभी एक असाइनमेंट बनाने के लिए उपयोग किया जाता है। FNR == NR NR == FNR से भिन्न होगा यदि असाइनमेंट के लिए डबल बराबर चिह्न का उपयोग किया जा रहा था। अतः किसी अनजान व्यक्ति के लिए, जैसे कि यह पूछने वाला, यह पूछने के लिए उचित है कि क्या वे समान हैं।
टोड वाल्टन

@ToddWalton अच्छा बिंदु! एक और उदाहरण: a='3x'; if [[ $a == 3* ]]; then echo yes; fiऔर आप दोनों पक्षों को स्विच नहीं कर सकते ==
वाल्टर ए

@WalterA हाँ यह सच है (बाश में, कम से कम)। क्या आप मेरे उत्तर में कोई सुधार करने का सुझाव दे रहे हैं?
टॉम फेन्च

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

72

फ़ाइल 2 में भी हैं कि key2 (लाइन का पहला शब्द) के लिए देखो।
चरण 1: फ़ाइल 1 के पहले शब्दों के साथ सरणी भरें:

awk '{a[$1];}' file1

चरण 2: सरणी भरें और उसी कमांड में फ़ाइल 2 को अनदेखा करें। इसके लिए वर्तमान इनपुट फ़ाइल की संख्या के साथ अब तक के रिकॉर्ड की कुल संख्या की जाँच करें।

awk 'NR==FNR{a[$1]}' file1 file2

चरण 3: }फ़ाइल 1 पार्स करने के बाद आने वाली क्रियाओं को अनदेखा करें

awk 'NR==FNR{a[$1];next}' file1 file2 

चरण 4: सरणी में पाए जाने पर फ़ाइल 2 की प्रिंट कुंजी

awk 'NR==FNR{a[$1];next} $1 in a{print $1}' file1 file2

4
इस वन-लाइनर का शानदार टेकडाउन। क्या चरण 1 में अर्धविराम आवश्यक है?
टॉमस गैंडर

2
@TomaszGandor चरण 1 में अर्धविराम की आवश्यकता नहीं है। मैं इसे चरण 3 में जोड़ सकता था, लेकिन ;nextएक अजीब जोड़ है ( nextचरण 3 में अर्धविराम जोड़ना और उसकी आवश्यकता है)। आप चरण 1 के साथ परीक्षण कर सकते हैं awk '{a[$1]} END { for (k in a) { print "a[k]=" k } }' file1
वाल्टर ए

45

ऊपर NRऔर FNRawk मैनुअल में देखें और फिर अपने आप से पूछें NR==FNRकि निम्नलिखित उदाहरण में वह कौन सी स्थिति है :

$ cat file1
a
b
c

$ cat file2
d
e

$ awk '{print FILENAME, NR, FNR, $0}' file1 file2
file1 1 1 a
file1 2 2 b
file1 3 3 c
file2 4 1 d
file2 5 2 e

क्या संसाधित की जा रही फ़ाइल की संख्या को प्रिंट करना भी संभव है? क्या इसके लिए एक अंतर्निहित चर है? (मुझे पता है कि हम उस के लिए एक चर बना सकते हैं और हर बार एनआर एक है इसे
बढ़ा सकते हैं

GNU में वह चर होता है ARGIND, अन्यथा आप कर सकते हैं FNR==1{ print ++file_nr }
एड मॉर्टन

यदि मैं किसी अन्य प्रश्न के साथ किसी प्रश्न का उत्तर दे
पाऊं तो वह उतना

मैंने एक सवाल नहीं पूछा, मैंने दिखाया कि ओपीएस प्रश्न का उत्तर कैसे प्राप्त किया जाए।
एड मॉर्टन

20

वहां awk बिल्ट-इन वैरिएबल।

NR - यह संसाधित किए गए रिकॉर्ड की कुल संख्या देता है।

FNR - यह प्रत्येक इनपुट फ़ाइल के लिए रिकॉर्ड की कुल संख्या देता है।


15

मान लें कि आपके पास फ़ाइलें a.txt और b.txt साथ हैं

cat a.txt
a
b
c
d
1
3
5
cat b.txt
a
1
2
6
7

ध्यान रखें एनआर और एफएनआर अंतर्निहित वैरिएबल हैं। एनआर - संसाधित किए गए रिकॉर्ड की कुल संख्या देता है। (इस मामले में a.txt और b.txt दोनों में) FNR - प्रत्येक इनपुट फ़ाइल के रिकॉर्ड की कुल संख्या देता है (रिकॉर्ड में या तो a.txt या b.txt)

awk 'NR==FNR{a[$0];}{if($0 in a)print FILENAME " " NR " " FNR " " $0}' a.txt b.txt
a.txt 1 1 a
a.txt 2 2 b
a.txt 3 3 c
a.txt 4 4 d
a.txt 5 5 1
a.txt 6 6 3
a.txt 7 7 5
b.txt 8 1 a
b.txt 9 2 1

एनआर == एफएनआर के साथ पहले मिलान को छोड़ने के लिए "अगला" जोड़ें

b.txt में और a.txt में

awk 'NR==FNR{a[$0];next}{if($0 in a)print FILENAME " " NR " " FNR " " $0}' a.txt b.txt
b.txt 8 1 a
b.txt 9 2 1

b.txt में लेकिन a.txt में नहीं

 awk 'NR==FNR{a[$0];next}{if(!($0 in a))print FILENAME " " NR " " FNR " " $0}' a.txt b.txt
b.txt 10 3 2
b.txt 11 4 6
b.txt 12 5 7

awk 'NR==FNR{a[$0];next}!($0 in a)' a.txt b.txt
2
6
7
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.