आप फिर से sed या awk को कॉल किए बिना स्ट्रिंग से डॉट कैरेक्टर कैसे हटा सकते हैं?


12

मेरे पास एक फाइल hostlist.txtहै जिसमें टेक्स्ट इस तरह है:

host1.mydomain.com
host2.mydomain.com
anotherhost
www.mydomain.com
login.mydomain.com
somehost
host3.mydomain.com

मेरे पास निम्नलिखित छोटी स्क्रिप्ट है:

#!/usr/local/bin/bash

while read host; do
        dig +search @ns1.mydomain.com $host ALL \
        | sed -n '/;; ANSWER SECTION:/{n;p;}';
done <hostlist.txt \
        | gawk '{print $1","$NF}' >fqdn-ip.csv

जिसके लिए आउटपुट fqdn-ip.csv:

host1.mydomain.com.,10.0.0.1
host2.mydomain.com.,10.0.0.2
anotherhost.internal.mydomain.com.,10.0.0.11
www.mydomain.com.,10.0.0.10
login.mydomain.com.,10.0.0.12
somehost.internal.mydomain.com.,10.0.0.13
host3.mydomain.com.,10.0.0.3

मेरा प्रश्न यह है कि मैं .अल्पविराम से ठीक पहले बिना आह्वान के sedया gawkफिर से कैसे हटाऊं ? क्या कोई ऐसा कदम है जो मैं मौजूदा sedया gawkकॉल में कर सकता हूं जो डॉट को छीन लेगा?

hostlist.txt इसमें मेजबानों की संख्या अधिक होगी, इसलिए मैं चाहता हूं कि मेरी स्क्रिप्ट तेज और कुशल हो।


2
किसी भी कारण से dig +shortआप के लिए काम नहीं करता है?
रोजर लिप्सकॉम्ब

@RogerLipscombe क्योंकि मेरे hostlist.txt में कुछ होस्ट केवल होस्टनाम हैं, न कि FQDNs इसलिए मैं उन्हें हल करने के लिए + खोज का उपयोग कर रहा हूं।
लीनोब

जवाबों:


18

sedआदेश, awkआदेश, और अनुगामी अवधि को हटाने के सभी एक ही awk आदेश में जोड़ा जा सकता:

while read -r host; do dig +search "$host" ALL; done <hostlist.txt | awk 'f{sub(/.$/,"",$1); print $1", "$NF; f=0} /ANSWER SECTION/{f=1}'

या, जैसा कि कई लाइनों में फैला हुआ है:

while read -r host
do
    dig +search "$host" ALL
done <hostlist.txt | awk 'f{sub(/.$/,"",$1); print $1", "$NF; f=0} /ANSWER SECTION/{f=1}'

क्योंकि awkकमांड doneस्टेटमेंट को फॉलो करता है , केवल एक awkप्रक्रिया को लागू किया जाता है। यद्यपि दक्षता यहां मायने नहीं रखती है, यह प्रत्येक लूप के साथ एक नई sed या awk प्रक्रिया बनाने की तुलना में अधिक कुशल है।

उदाहरण

इस परीक्षण फ़ाइल के साथ:

$ cat hostlist.txt 
www.google.com
fd-fp3.wg1.b.yahoo.com

आदेश का उत्पादन:

$ while read -r host; do dig +search "$host" ALL; done <hostlist.txt | awk 'f{sub(/.$/,"",$1); print $1", "$NF; f=0} /ANSWER SECTION/{f=1}'
www.google.com, 216.58.193.196
fd-fp3.wg1.b.yahoo.com, 206.190.36.45

यह काम किस प्रकार करता है

awk एक समय में अपने इनपुट एक रिकॉर्ड (लाइन) को पढ़ता है। यह awk स्क्रिप्ट एकल चर का उपयोग करता है f, जो संकेत देता है कि पिछली पंक्ति एक उत्तर अनुभाग हेडर थी या नहीं।

  • f{sub(/.$/,"",$1); print $1", "$NF; f=0}

    यदि पिछली पंक्ति एक उत्तर अनुभाग हेडर थी, तो fयह सच होगा और घुंघराले ब्रेसिज़ में कमांड निष्पादित किए जाते हैं। पहले क्षेत्र से अनुगामी अवधि को हटाता है। दूसरा पहले फील्ड को प्रिंट करता है ,, उसके बाद आखिरी फील्ड को। तीसरा कथन fशून्य (असत्य) पर रीसेट करता है।

    दूसरे शब्दों में, fयहाँ एक तार्किक स्थिति है। घुंघराले ब्रेसिज़ में आदेशों को निष्पादित किया जाता है यदि fनॉनज़रो (जो कि awk में है, जिसका अर्थ है 'सत्य')।

  • /ANSWER SECTION/{f=1}

    यदि वर्तमान लाइन में स्ट्रिंग है ANSWER SECTION, तो चर (सच) पर fसेट है 1

    यहाँ, /ANSWER SECTION/एक तार्किक स्थिति के रूप में कार्य करता है। यह सही का मूल्यांकन करता है अगर वर्तमान नियमित अभिव्यक्ति से मेल खाता है ANSWER SECTION। यदि यह होता है, तो निष्पादित में कमांड को घुंघराले ब्रेसिज़ में।


धन्यवाद @ जॉन 1024! मुझे नहीं पता था कि awk को लूप के भीतर होने की ज़रूरत नहीं है (मुझे लगता है कि यह केवल अंतिम पंक्ति पर कार्य करेगा यदि यह बाहर था)। है fएक मनमाना चर या है f{}awk की कार्यक्षमता का एक स्पष्ट हिस्सा है?
लीनोब

आपका स्वागत है। fएक मनमाना चर है। आप वास्तव में {}जटिल तार्किक परिस्थितियों के सामने रख सकते हैं। fबस एक बहुत ही सरल तार्किक स्थिति है: यह सत्य है यदि गैर-शून्य, झूठ यदि शून्य है।
जॉन १०२४

@ लिनोब ने ध्यान दिया कि दूसरी कमांड में, /ANSWER SECTION/तार्किक स्थिति की भूमिका निभाता fहै, पहले कमांड में निभाई गई भूमिका के अनुरूप है । मैंने इस पर चर्चा करने का उत्तर अपडेट कर दिया है।
जॉन १०२४

7

digहोस्टनाम की सूची वाली फ़ाइल में पढ़ सकते हैं और उन्हें एक-एक करके संसाधित कर सकते हैं। आप digउत्तर अनुभाग को छोड़कर सभी आउटपुट को दबाने के लिए भी कह सकते हैं ।

यह आपको वह आउटपुट देना चाहिए जो आप चाहते हैं:

dig -f hostlist.txt +noall +answer +search | 
    awk '{sub(/\.$/,"",$1); print $1","$5}'

awkके sub()समारोह शाब्दिक अवधि पट्टी प्रयोग किया जाता है .पहले क्षेत्र के अंत से। फिर awkफ़ील्ड 1 और 5 को एक अल्पविराम से अलग करता है।

नोट: इसमें जो प्रविष्टियाँ hostlist.txtहल नहीं होती हैं, उन्हें पूरी तरह से छोड़ दिया जाता है - वे stdout या stderr पर प्रदर्शित नहीं होती हैं।

(लिनक्स और FreeBSD पर परीक्षण किया गया)


6

अपने आह्वान gawkको निम्नलिखित में बदलें :

| gawk '{print substr($1,1,length($1)-1)","$NF}' >fqdn-ip.csv
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.