अंतिम x आवृत्तियों को छोड़कर किसी वर्ण को बदलें


9

मेरे पास एक फाइल है जिसमें IPs के साथ सहसंबंधित होस्टनाम का एक गुच्छा है जो इस तरह दिखता है:

x-cluster-front-1 192.168.1.2
x-cluster-front-2 192.158.1.10
y-cluster-back-1 10.1.11.99
y-cluster-back-2 10.1.157.38
int.test.example.com 59.2.86.3
super.awesome.machine 123.234.15.6

मैं इसे इस तरह देखना चाहता हूं:

x-cluster-front-1 192.168.1.2
x-cluster-front-2 192.158.1.10
y-cluster-back-1 10.1.11.99
y-cluster-back-2 10.1.157.38
int-test-example-com 59.2.86.3
super-awesome-machine 123.234.15.6

मैं कैसे प्रतिस्थापित कर सकता हूं (डॉट्स) पहले कॉलम से - (हाइफ़न) दूसरे कॉलम द्वारा सॉर्ट करने के लिए? मैं पहली जगह तक डॉट्स को बदलने के लिए sed का उपयोग करने के बारे में सोच रहा था, या हर डॉट को प्रतिस्थापित कर रहा था लेकिन अंतिम तीन, लेकिन मुझे रेगेक्स और sed समझने में परेशानी हो रही है। मैं सरल रीप्लेस कर सकता हूं लेकिन यह मेरे सिर पर है!

यह एक बड़ी स्क्रिप्ट का हिस्सा है जिसे मैं बैश में लिख रहा हूं। मैं इस हिस्से में फंस गया हूं।

जवाबों:


7

आप AWK का उपयोग कर सकते हैं

awk '{gsub(/-/,".",$1);print}' infile

व्याख्या

awkडिफ़ॉल्ट रूप से व्हाट्सएप पर एक लाइन को विभाजित करता है। इस प्रकार, रेखा (के पहले कॉलम $1में awk-ese) एक तुम पर प्रतिस्थापन करना चाहते हो जाएगा। इस प्रयोजन के लिए, आप इसका उपयोग कर सकते हैं:

 gsub(regex,replacement,string)

आवश्यक प्रतिस्थापन करने के लिए।

ध्यान दें कि gsubकेवल के लिए समर्थित है gawkऔर nawkकई आधुनिक डिस्ट्रो awkपर एक सॉफ्टलिंक है gawk


1
+1 यह मुझे हराया। मुझे लगता है कि एक स्पष्टीकरण वास्तव में पूछने वाले और भविष्य के पाठकों को भी लाभान्वित करेगा।
जोसेफ आर।

1
@JosephR। क्षमा करें, मैं स्पष्टीकरण में अच्छा नहीं हूं, लेकिन मैंने कोशिश की है और अद्यतन किया है ..
राहुल पाटिल

2
POSIX कल्पना awkपर आधारित है nawk, इसलिए सभी आधुनिक awkकार्यान्वयन होना चाहिए gsub। सोलारिस पर, आपको आवश्यकता हो सकती है /usr/xpg4/bin/awkया nawk
स्टीफन चेज़लस

@RahulPatil यदि आपको कोई आपत्ति नहीं है, तो मैंने कुछ पंक्तियाँ जोड़ीं जो मुझे लगता है कि दूसरों की मदद करेगी।
जोसेफ आर।

@ जोसेफ थैंक्स .., अब बिल्कुल सही लग रहा है .. :)
राहुल पाटिल

6

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

आप इसे लिखने के बजाय इससे बच सकते हैं:

perl -pe 's|\S+|$&=~tr/./-/r|e' file

-pध्वज का अर्थ है "लाइन द्वारा इनपुट फ़ाइल लाइन पढ़ सकते हैं और स्क्रिप्ट के द्वारा दिए गए आवेदन करने के बाद प्रत्येक पंक्ति मुद्रित -e"। फिर, प्रतिस्थापन ( s|pattern|replacement|) \S+मिलान किए गए पैटर्न के साथ गैर-अंतरिक्ष वर्णों का पहला क्रम ( $&) सब के .साथ प्रतिस्थापित करने के बाद -। चाल का उपयोग करना है s|||eजहां eऑपरेटर एक प्रतिस्थापन के रूप में अभिव्यक्ति का मूल्यांकन करेगा। तो, आपके पास पिछले एक ( ) tr/./-/के मैच के लिए एक प्रतिस्थापन ( ) लागू हो सकता है ।$&s|||e

आप हर स्थानापन्न करने की जरूरत है .एक साथ -जीएनयू साथ पिछले 3 पिछले लोगों को छोड़कर, sedऔर यह सोचते हैं आप एक है revआदेश:

rev file | sed 's/\./-/4g' | rev

1
ध्यान दें कि पर्ल समाधान संस्करण 5.14 या उच्चतर ( /rकाम करने के लिए) मानता है ।
जोसेफ आर।

3

सैड काम के लिए सबसे आसान उपकरण नहीं है - बेहतर उपकरणों के लिए अन्य उत्तर देखें - लेकिन यह किया जा सकता है।

बदलने के लिए .द्वारा -केवल पहली अंतरिक्ष, उपयोग करने के लिए sएक पाश में।

sed -e '
  : a                     # Label "a" for the branching command
  s/^\([^ .]*\)\./\1-/    # If there is a "." before the first space, replace it by "-"
  t a                     # If the s command matched, branch to a
'

(ध्यान दें कि कुछ sed कार्यान्वयन समान लाइन पर टिप्पणियों का समर्थन नहीं करते हैं। GNU sed करता है।)

इसके बजाय अंतिम स्थान तक प्रतिस्थापन करने के लिए:

sed -e '
  : a                     # Label "a" for the branching command
  s/\.\(.* \)/-\1/        # If there is a "." before the last space, replace it by "-"
  t a                     # If the s command matched, branch to a
'

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

sed -e '
  h           # Save the current line to the hold space
  s/.* / /    # Remove everything up to the last space
  x           # Swap the work space with the hold space
  s/[^ ]*$//  # Remove everything after the last space
  y/./-/      # Replace all "." by "-"
  G           # Append the content of the hold to the work space
  s/\n//      # Remove the newline introduced by G
'

2

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

perl -pe '
    $count = tr{.}{.}; # Count '.' on the current line
    $x = 3;
    next LINE if $count <= $x;
    while(s{\.}{-}){   # Substitute one '.' with a '-'
        last if ++$i == $count - $x # Quit the loop before the last x substitutions
    }
$i = 0
' your_file

उपरोक्त कोड (परीक्षण किया गया) यह नहीं मानता है कि आपके पास अंतरिक्ष-अलग क्षेत्र हैं। यह अंतिम 3 बिंदुओं को छोड़कर सभी बिंदुओं को एक पंक्ति में डैश के साथ बदल देगा। 3कोड को अपनी पसंद के अनुसार बदलें ।


2

आप इसके लिए कई विभिन्न उपकरणों का उपयोग कर सकते हैं। राहुल पाटिल ने आपको पहले से ही एक दिया था gawkइसलिए यहां कुछ और हैं:

  • पर्ल

    perl -lane  '$F[0]=~s/\./-/g; print "@F"' file
    

    -aस्विच कारणों से व्हाइटस्पेस पर और सेव सरणी में जिसके परिणामस्वरूप फ़ील्ड अपने आप विभाजन इनपुट लाइनों के लिए पर्ल @F। पहले क्षेत्र है, इसलिए, हो जाएगा $F[0]तो हम की जगह ( s///) की सभी घटनाओं .के साथ -पहले क्षेत्र में और उसके बाद पूरे सरणी मुद्रित करें।

  • खोल

     while read -r a b; do printf "%s %s\n" "${a//./-}" "$b"; done < file 
    

    यहाँ, जबकि लूप फ़ाइल पढ़ता है और स्वचालित रूप से व्हाट्सएप पर विभाजित होता है। यह दो फ़ील्ड बनाता है, $firstऔर $rest। निर्माण ${first//pattern/replacement}के patternसाथ सभी घटनाओं को प्रतिस्थापित करता है replacement


+1 जबकि perlrun(1)आप बताएंगे कि -a"ऑटोसप्लिट मोड" है, मैं इसे " awkमोड" के रूप में सोचना पसंद करता हूं : D
जोसेफ आर।

2

मेरा मानना ​​है कि बड़े नॉटी रेगेक्स की तुलना में यह पढ़ना थोड़ा आसान है। मूल रूप से मैं सिर्फ व्हाट्सएप पर दो क्षेत्रों में लाइन को विभाजित करता हूं और पहले भाग पर sed का उपयोग करता हूं।

while read -r host ip; do
    echo "$(sed 's/\./-/g' <<< "$host") $ip"
done < input_file

आपके शेल के आधार पर आप sed कमांड के बजाय $ {host //./-} का उपयोग कर सकते हैं।


0
sed 's/\./-/' <file name>

gकमांड के अंत में उपयोग किए बिना आप यह कर सकते हैं ... यह बस पैटर्न के 1 कोस्टिसेशन को बदल देगा

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