गॉक इनकम और स्टडआउट


10

यह उपयोग करना संभव है gawkके -i inplaceविकल्प और भी चीजों को प्रिंट stdout?

उदाहरण के लिए, यदि मैं किसी फ़ाइल को अद्यतन करना चाहता था, और यदि कोई परिवर्तन हो तो फ़ाइल का नाम और मेरे द्वारा बदली गई पंक्तियों को प्रिंट stderrकर सकते हैं।

find -type f -name 'myfiles' -exec gawk -i inplace '{if(gsub(/pat/, "repl")) { print FILENAME > "/proc/self/fd/2" ; print > "/proc/self/fd/2"; } print;}' {} +

लेकिन क्या stdoutइसके बजाय उपयोग करने का एक तरीका है , या उस ब्लॉक को वैकल्पिक स्ट्रीम में प्रिंट करने के लिए एक क्लीनर तरीका है?


2
इस विशेष मामले में आप कुछ इस तरह से चलाना चाह सकते हैं find -type f -name 'myfiles' -exec grep -q 'pattern' {} \; -print -exec gawk -i inplace '{do_your_sub_and_print_to_dev/stderr_too}' {} \;कि आप केवल उन फ़ाइलों को संपादित करने के लिए awk का उपयोग करेंगे जिनमें वास्तव में उस पैटर्न से मेल खाती लाइनें हैं।
don_crissti

@don_crissti मैं अक्सर भूल जाता हूं कि कितना तेज grepहो सकता है। मेरी पहली वृत्ति फ़ाइल को दो बार "प्रोसेस" करने से बचने के लिए है, लेकिन मुझे बिल्कुल आश्चर्य नहीं होगा अगर यह वास्तव में तेज है। यह सिर्फ यह दिखाने के लिए जाता है कि मैं प्रोफाइलिंग कार्यों पर अपनी आंत पर भरोसा क्यों कर सकता हूं
एरिक रेनॉफ

1
हां, यह काफी तेज है और ध्यान रखें कि: 1) अगर कोई मैच नहीं है, तो आप केवल एक बार फाइल को प्रोसेस करते हैं (जिस हिस्से को -print -exec gawkअब निष्पादित नहीं किया गया है) और 2) यह 1 मैच पर रुक जाएगा, जब तक कि 1 मैच न हो अंतिम पंक्ति आप अभी भी पूरी फ़ाइल को दो बार संसाधित नहीं कर रहे हैं (यह 1.X बार की तरह अधिक है)। इसके अलावा, अगर यह gawk -i inplaceकाम करता है तो sed -iयह फाइल को इन-प्लेस पर एडिट करेगा - यानी टाइमस्टैम्प, इनकोड आदि को अपडेट करने पर भी, अगर एडिट करने के लिए कुछ नहीं था ...
don_crissti

जवाबों:


13

आपको इसके बजाय /dev/stderrया का उपयोग करना चाहिए । हैंडल और खुद से (परवाह किए बिना कि सिस्टम में वे फाइलें हैं या नहीं)।/dev/fd/2/proc/self/fd/2gawk/dev/fd/x/dev/stderr

जब आप एक:

print "x" > "/dev/fd/2"

gawkएक करता है write(2, "x\n"), जबकि जब आप करते हैं:

print "x" > "/proc/self/fd/2"

क्योंकि यह /proc/self/fd/xविशेष रूप से इलाज नहीं करता है , यह एक करता है:

fd = open("/proc/self/fd/2", O_WRONLY|O_CREAT|O_TRUNC);
write(fd, "x\n");

पहले /proc/self/fdलिनक्स विशिष्ट है और लिनक्स पर वे समस्याग्रस्त हैं। ऊपर दिए गए दो संस्करण समतुल्य नहीं हैं जब stderr एक नियमित या अन्य खोजी फ़ाइल के लिए या सॉकेट के लिए है (जिसके लिए उत्तरार्द्ध विफल होगा) (यह उल्लेख करने के लिए नहीं कि यह फ़ाइल डिस्क्रिप्टर को बर्बाद करता है)।

यह कहा जा रहा है, यदि आपको मूल stdout को लिखने की आवश्यकता है, तो आपको इसे अन्य fd में सहेजने की आवश्यकता है जैसे:

gawk -i inplace '{
   print "goes into the-file"
   print "to stdout" > "/dev/fd/3"}' the-file 3>&1

gawkफ़ाइल में इन-प्लेस के साथ रीडायरेक्ट करता है। उदाहरण के लिए इसकी आवश्यकता है, आप चाहते हैं:

awk -i inplace '{system("uname")}' file

में unameउत्पादन को स्टोर करने के लिए file


2

सिर्फ मनोरंजन के लिए, एक वैकल्पिक केवल POSIX का उपयोग कर दृष्टिकोण की सुविधाओं find, sh, grepऔर (सबसे विशेष) ex:

find . -type f -name 'myfiles' -exec sh -c '
  for f do grep -q "pat" "$f" &&
    { printf "%s\n" "$f";
      printf "%s\n" "%s/pat/repl/g" x | ex "$f";
  }; done' find-sh {} +

(उपरोक्त कमांड में सभी लाइन ब्रेक वैकल्पिक हैं; इसे एक-लाइनर के लिए संघनित किया जा सकता है।)

या, यकीनन कानूनी रूप से अधिक:

find . -type f -name 'myfiles' -exec sh -c '
  for f
  do
    if grep -q "pat" "$f"; then
      printf "%s\n" "$f"
      printf "%s\n" "%s/pat/repl/g" x | ex "$f"
    fi
  done' find-sh {} +

:)


(यह कमांड अनटाइटेड है; यदि मेरा कोई भी नासमझ बना है तो संपादन का स्वागत है।)

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