जागना क्यों रुक जाता है और अगर फ़ाइलनाम में = = और उसके आस-पास कैसे काम करना है, प्रतीक्षा करें?


25
awk 'processing_script_here' my=file.txt

अनिश्चित काल तक रुकना और प्रतीक्षा करना लगता है ... यहां
क्या हो रहा है और मैं इसे कैसे काम करूं?


जवाबों:


19

जैसा कि क्रिस कहते हैं , इनपुट फ़ाइल नामों के बजाय variablename=anything(नए ( -v var=valueजो BEGIN) कथन से पहले किए गए हैं ) के विपरीत , फॉर्म के तर्कों को चर असाइनमेंट के रूप में माना जाता है (उस समय जो तर्कों को संसाधित किया जाता है )।

यह इस तरह की चीजों में उपयोगी हो सकता है:

awk '{print $1}' FS=/ RS='\n' file1 FS='\n' RS= file2

जहाँ आप एक अलग FS/ RSप्रति फ़ाइल निर्दिष्ट कर सकते हैं । यह आमतौर पर भी उपयोग किया जाता है:

awk '!file1_processed{a[$0]; next}; {...}' file1 file1_processed=1 file2

इसका एक सुरक्षित संस्करण है:

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

(जो file1खाली है तो काम नहीं करता है)

लेकिन यह उस तरह से हो जाता है जब आपके पास फाइलें होती हैं जिनके नाम में =अक्षर होते हैं।

अब, यह केवल एक समस्या है जब पहली बार छोड़ दिया गया =एक वैध awkचर नाम है।

में एक वैध चर नाम का गठन awkकिसकी तुलना में कठोर है sh

POSIX के लिए कुछ ऐसा होना आवश्यक है:

[_a-zA-Z][_a-zA-Z0-9]*

पोर्टेबल चरित्र सेट के केवल पात्रों के साथ। हालांकि, /usr/xpg4/bin/awkसोलारिस 11 कम से कम उस संबंध में आज्ञाकारी नहीं है और किसी भी वर्णक्रम के वर्णों को केवल नाम के ही नहीं, बल्कि चर नामों में स्थानिक नाम से अनुमति देता है।

तो जैसे एक तर्क x+y=fooया =barया ./foo=barअभी भी कोई इनपुट फ़ाइल नाम और नहीं एक काम के रूप में व्यवहार किया जाता है के रूप में क्या बचा है की पहले =एक वैध चर नाम नहीं है। कार्यान्वयन और स्थान के Stéphane=Chazelas.txtआधार पर एक तर्क जैसा हो सकता है या नहीं awk

यही कारण है कि awk के साथ, इसका उपयोग करने की अनुशंसा की जाती है:

awk '...' ./*.txt

के बजाय

awk '...' *.txt

उदाहरण के लिए समस्या से बचने के लिए यदि आप txtफ़ाइलों के नाम की गारंटी नहीं दे सकते हैं तो इसमें =अक्षर नहीं होंगे ।

इसके अलावा, सावधान रहें कि -vfoo=bar.txtयदि आप उपयोग करते हैं तो एक तर्क को एक विकल्प के रूप में माना जा सकता है:

awk -f file.awk -vfoo=bar.txt

(यह भी लागू होता है awk '{code}' -vfoo=bar.txtके साथ awkबिजीबॉक्स संस्करणों से 1.28.0 करने से पहले, देखें बग रिपोर्ट इसी )।

फिर, इसके ./*.txtचारों ओर काम का उपयोग करना (एक ./उपसर्ग का उपयोग करना भी एक फ़ाइल के साथ मदद करता है जिसे बुलाया जाता है -अन्यथा अन्यथा मानक इनपुट केawk रूप में समझा जाता है )।

इसीलिए भी

#! /usr/bin/awk -f

शेबंग वास्तव में काम नहीं करते हैं। जबकि मानों को एक कथन में मानों var=valueको ठीक करके ARGV(किसी ./उपसर्ग को जोड़कर ) काम किया जा सकता है BEGIN:

#! /usr/bin/awk -f
BEGIN {
  for (i = 1; i < ARGC; i++)
    if (ARGV[i] ~ /^[_[:alpha:]][_[:alnum:]]*=/)
      ARGV[i] = "./" ARGV[i]
}
# rest of awk script

यह उन लोगों के विकल्प के साथ मदद नहीं करेगा जैसा कि उन लोगों द्वारा देखा जाता है awkऔर awkस्क्रिप्ट नहीं ।

उस ./उपसर्ग का उपयोग करने के साथ एक संभावित कॉस्मेटिक मुद्दा यह समाप्त हो गया है FILENAME, लेकिन substr(FILENAME, 3)यदि आप नहीं चाहते हैं तो आप इसे हमेशा पट्टी करने के लिए उपयोग कर सकते हैं ।

जीएनयू कार्यान्वयन awkउन सभी मुद्दों को इसके -Eविकल्प के साथ ठीक करता है ।

के बाद -E, gawk केवल awkस्क्रिप्ट के पथ (जहां -अभी भी स्टडिन का मतलब है) की उम्मीद करता है और फिर केवल इनपुट फ़ाइल पथों की एक सूची (और वहां, -विशेष रूप से इलाज भी नहीं किया जाता है)।

इसके लिए विशेष रूप से डिज़ाइन किया गया है:

#! /usr/bin/gawk -E

शेबबैंग्स जहां तर्कों की सूची हमेशा इनपुट फाइलें होती है (ध्यान दें कि आप अभी भी उस कथन ARGVमें उस सूची को संपादित करने के लिए स्वतंत्र हैं BEGIN)।

आप इसका उपयोग इस रूप में भी कर सकते हैं:

gawk -e '...awk code here...' -E /dev/null *.txt

हम -Eखाली स्क्रिप्ट के साथ उपयोग करते हैं ( /dev/null) बस यह सुनिश्चित करने के लिए कि *.txtबाद में उन्हें हमेशा इनपुट फ़ाइलों के रूप में माना जाता है, भले ही वे =वर्ण हों।


मैं यह नहीं देखता कि FILENAME में समाप्त होने वाला स्पष्ट मार्ग एक समस्या कैसे है। या तो awk script सामान्य है, जिस स्थिति में उसे FILENAME में समाप्त होने वाले सभी प्रकार के रास्तों को संभालना चाहिए (जिसमें सीमित नहीं है ../foo, /path/to/fooऔर एक अलग एन्कोडिंग में मौजूद पथ हैं) - जिस स्थिति substr(FILENAME,3)में यह पर्याप्त नहीं होगा, या यह नहीं है एक एक शॉट स्क्रिप्ट जहां उपयोगकर्ता मूल रूप से जानता है क्या फ़ाइल नाम हैं - जो मामले में / वह शायद उनमें से किसी से युक्त के साथ परेशान नहीं करना चाहिए =या तो ;-)
mosvy

2
@ मैं यह नहीं समझता कि ./यह एक समस्या है, लेकिन यह कहा जाता है कि यह कुछ शर्तों के तहत अवांछनीय हो सकता है, जैसे कि ऐसे मामले जिनमें फ़ाइल नाम को आउटपुट में शामिल किया ./जाना है , जिसमें मामला अनावश्यक और अनावश्यक होना चाहिए, इसलिए आप 'किसी तरह इससे छुटकारा पाना होगा। यहाँ कम से कम एक उदाहरण है । जैसा कि उपयोगकर्ता जानते हैं कि फ़ाइल नाम क्या हैं - ठीक है, इस मामले में हम यह भी जानते हैं कि फ़ाइल नाम क्या है, लेकिन =अभी भी उचित प्रसंस्करण के रास्ते में है। तो अग्रणी -रास्ते में मिल सकता है ।
सर्गी कोलोडाज़नी

@mosvy, हां विचार यह है कि आप ./उस awk(गलत) विशेषता के आसपास काम करने के लिए उपसर्ग का उपयोग करना चाहते हैं लेकिन फिर आप ./आउटपुट पर उस के साथ समाप्त होते हैं जिसे आप पट्टी करना चाहते हैं। देखें कि कैसे जांच करें कि फ़ाइल की पहली पंक्ति में एक विशिष्ट स्ट्रिंग है? उदहारण के लिए।
स्टीफन चेज़लस

न केवल स्थानीय (इस निर्देशिका के सापेक्ष) है, ./बल्कि वैश्विक (निरपेक्ष पथ) भी है /जो एक फ़ाइल के रूप में तर्क की व्याख्या करता है।
इसहाक

21

जाग के अधिकांश संस्करणों में, प्रोग्राम को निष्पादित करने के लिए तर्क या तो हैं:

  1. एक पंक्ति
  2. प्रपत्र का असाइनमेंट x=y

चूँकि आपके फ़ाइलनाम की व्याख्या केस # 2 के रूप में की जा रही है, awk अभी भी स्टडिन पर कुछ पढ़ने के लिए प्रतीक्षा कर रहा है (क्योंकि यह अनुभव नहीं करता है कि कोई फ़ाइल नाम पारित किया गया है)।

संभवतः, यह व्यवहार POSIX में प्रलेखित है :

निम्नलिखित में से दो प्रकार के तर्क आपस में जुड़े हो सकते हैं:

  • फ़ाइल: एक फ़ाइल का एक पथनाम जिसमें पढ़ने के लिए इनपुट होता है, जिसे प्रोग्राम में पैटर्न के सेट के साथ मिलान किया जाता है। यदि कोई फ़ाइल ऑपरेटर निर्दिष्ट नहीं है, या यदि कोई फ़ाइल ऑपरेंड '-' है, तो मानक इनपुट का उपयोग किया जाएगा।
  • असाइनमेंट: एक ऑपरेंड जो पोर्टेबल कैरेक्टर सेट से अंडरस्कोर या अल्फाबेटिक कैरेक्टर से शुरू होता है (टेबल को IEEE Std 1003.1-2001, सेक्शन 6.1, पोर्टेबल कैरेक्टर सेट के बेस डेफिनेशन वॉल्यूम में देखें), इसके बाद अंडरस्कोर, डिजिट का एक सिक्वेंस आता है। और पोर्टेबल वर्ण सेट से वर्णमाला, उसके बाद '=' वर्ण, एक मार्गनाम के बजाय एक चर असाइनमेंट निर्दिष्ट करेगा।

जैसे कि, सुस्पष्ट रूप से, आपके पास कुछ विकल्प हैं (# 1 संभवतः कम से कम घुसपैठ है):

  1. का उपयोग करें awk ... ./my=file, जो इस के बाद .से "पोर्टेबल चरित्र सेट से एक अंडरस्कोर या अक्षर चरित्र" नहीं है।
  2. फ़ाइल का उपयोग स्टड पर रखें awk ... < my=file। हालाँकि, यह कई फ़ाइलों के साथ अच्छी तरह से काम नहीं करता है।
  3. अस्थायी रूप से फ़ाइल के लिए एक हार्डलिंक बनाएं, और उसका उपयोग करें। आप ऐसा कुछ कर सकते हैं ln my=file my_file, और फिर my_fileसामान्य रूप से उपयोग कर सकते हैं । कोई भी नकल नहीं की जाएगी, और दोनों फ़ाइलों को एक ही डेटा और इनकोड मेटाडेटा द्वारा समर्थित किया जाएगा। इसका उपयोग करने के बाद, लिंक को हटाने के लिए सुरक्षित है क्योंकि इनोड के संदर्भों की संख्या अभी भी 0 से अधिक होगी।

6
./my=file काम नहीं करता है? % awk 'processing_script_here' ./my=file.txt awk: fatal: cannot open file ./my=file.txt' for reading (No such file or directory). यह पोर्टेबल होना चाहिए क्योंकि ./myएक मान्य चर नाम नहीं है, इसलिए इस तरह से पार्स नहीं किया जाना चाहिए।
स्टीफन हैरिस

2
जैसा कि POSIX पाठ कहता है, समस्या केवल तब होती है जब =पहले पोर्टेबल चरित्र सेट से एक अंडरस्कोर या अल्फाबेटिक चरित्र से पहले होता है (IEEE Std 1003.1-2001, धारा 6.1, पोर्टेबल चरित्र सेट के बेस डेफिनेशन वॉल्यूम में तालिका देखें), पोर्टेबल वर्ण सेट से अंडरस्कोर, अंक और वर्णमाला के अनुक्रम के बाद । इसलिए की तरह एक फ़ाइल पथ ++foo=bar.txtया =fooया ./foo=barसब ठीक हैं के रूप में है कि .या +एक नहीं है [_a-zA-Z]
स्टीफन चेज़लस

1
@SergiyKolodyazhnyy अवेक शेल के लिए बाहरी है, इसलिए यह कोई फर्क नहीं पड़ता कि आप किसका उपयोग करते हैं। ./my=fileवर्बेटिम के माध्यम से पारित किया जाएगा।
क्रिस डाउन

1
@SergiyKolodyazhnyy, के लिए ही awk '{print $1,$2}' /etc/passwd। मुद्दा यह है कि शेल को खोलने के लिए फ़ाइल को खोलने के विपरीत जागने से कोई फर्क नहीं पड़ता है क्योंकि यह इसे खोजने योग्य बनाता है या नहीं। वास्तव में awk '{exit}' < /etc/passwd, आप यह सुनिश्चित करने awkके लिए पहले रिकॉर्ड के अंत में वापस जाने की अपेक्षा करेंगे exitकि यह सुनिश्चित करने के लिए कि यह स्टड के भीतर स्थिति को छोड़ देता है। POSIX की आवश्यकता है कि /usr/xpg4/bin/awkSolaris पर करता है, लेकिन GNU / Linux पर न तो ऐसा लगता है gawkऔर न ही mawkऐसा लगता है।
स्टीफन चेज़लस

3
@mosvy, INPUT FILES अनुभाग को pubs.opengroup.org/onlinepubs/9699919799/utilities/ पर देखें। यह कई उपयोग पैटर्न में उपयोगी है जो केवल नियमित फ़ाइलों के साथ समझ में आता है, जैसे कि आप किसी फ़ाइल को रौंदना चाहते हैं या उसमें डेटा लिखना चाहते हैं। इस तरह से एक स्थिति की पहचान की awk
स्टीफन चेज़लस

3

गॉक डॉक्युमेंटेशन को उद्धृत करने के लिए (नोट जोर जोड़ा):

कमांड लाइन पर किसी भी अतिरिक्त तर्क को सामान्यतः निर्दिष्ट आदेश में संसाधित की जाने वाली इनपुट फ़ाइलों के रूप में माना जाता है। हालाँकि, एक तर्क जिसके पास var var = value है, वैरिएबल var के मान को असाइन करता है - यह किसी फ़ाइल को निर्दिष्ट नहीं करता है।

आज्ञा रुककर इंतजार क्यों करती है? क्योंकि प्रपत्र में उपरोक्त परिभाषा द्वारा awk 'processing_script_here' my=file.txt निर्दिष्ट कोई फ़ाइल नहीं है - my=file.txtचर असाइनमेंट के रूप में व्याख्या की गई है, और यदि कोई फ़ाइल परिभाषित नहीं है, तो awkस्टडिन (यह भी स्पष्ट है straceकि यह दर्शाता है कि इस तरह के कमांड में awk read(0,'...)syscall पर प्रतीक्षा कर रहा है ।

यह भी POSIX awk विनिर्देशों में प्रलेखित है , OPERANDS अनुभाग और उस के कार्य भाग देखें )

वैरिएबल असाइनमेंट awk '{print foo}' foo=bar /etc/passwdउस मूल्य के रूप में स्पष्ट है जो fooप्रत्येक पंक्ति के लिए / etc / passwd में मुद्रित होता है। निर्दिष्ट ./foo=barया पूर्ण पथ हालांकि काम करता है।

ध्यान दें कि चल straceपर awk '1' foo=barऔर साथ ही साथ की जाँच cat foo=barसे पता चलता है कि इस awk विशेष मुद्दा है, और के रूप में तर्क पारित कर दिया execve शो फ़ाइल नाम करता है, तो गोले इस मामले में env चर असाइनमेंट से कोई संबंध नहीं है।

इसके अतिरिक्त, कृपया ध्यान दें कि awk '...script...' foo=barशेल द्वारा पर्यावरण चर सृजन नहीं होगा, क्योंकि पर्यावरण चर असाइनमेंट को प्रभावी होने के लिए एक कमांड से पहले होना चाहिए। POSIX शैल व्याकरण नियम देखें , अंक संख्या 7. इसके अतिरिक्त इसके माध्यम से सत्यापित किया जा सकता हैawk '{print ENVIRON["foo"]}' foo=bar /etc/passwd

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