सेड के साथ केस मैचिंग पैटर्न रिप्लेसमेंट


14

मेरे पास कई फ़ाइलों में एक स्रोत कोड है।

  • इसका एक पैटर्न है abcdefजिसे मुझे बदलने की आवश्यकता है pqrstuvxyz
  • पैटर्न Abcdef(सेंटेंस केस) हो सकता है, फिर इसे बदलने की जरूरत है Pqrstuvxyz
  • पैटर्न हो सकता है AbCdEf(टॉगल मामला) तो इसे बदलने की आवश्यकता है PqRsTuVxYz

संक्षेप में, मुझे स्रोत पैटर्न के मामले से मेल खाना चाहिए और उचित गंतव्य पैटर्न लागू करना चाहिए।

मैं इसका उपयोग करके sedया किसी अन्य उपकरण को कैसे प्राप्त कर सकता हूं ?


और अगर है ABcDeF?
स्टीफन चेज़लस

PQrStUvxyz - मुझे आपकी बात अच्छी लगी।
user1263746

तो अगर ABcDeF-> PQrStUvxyz, तो निश्चित रूप से AbCdEf-> PqRsTuvxyzतार्किक रूप से सुसंगत होगा। यदि मामले को एक स्ट्रिंग से दूसरे में कॉपी किया जाना है, तो दूसरा प्रतिस्थापन स्ट्रिंग अधिक लंबा होने पर क्या होना चाहिए।
ग्रीम

अच्छी तरह से संक्षिप्तता के लिए "pqrstu" के प्रतिस्थापन को ट्रिम कर देता है।
user1263746

जवाबों:


9

पोर्टेबल समाधान का उपयोग कर sed:

sed '
:1
/[aA][bB][cC][dD][eE][fF]/!b
s//\
&\
pqrstu\
PQRSTU\
/;:2
s/\n[[:lower:]]\(.*\n\)\(.\)\(.*\n\).\(.*\n\)/\2\
\1\3\4/;s/\n[^[:lower:]]\(.*\n\).\(.*\n\)\(.\)\(.*\n\)/\3\
\1\2\4/;t2
s/\n.*\n//;b1'

यह GNU sed के साथ थोड़ा आसान है:

search=abcdef replace=pqrstuvwx
sed -r ":1;/$search/I!b;s//\n&&&\n$replace\n/;:2
    s/\n[[:lower:]](.*\n)(.)(.*\n)/\l\2\n\1\3/
    s/\n[^[:lower:]](.*\n)(.)(.*\n)/\u\2\n\1\3/;t2
    s/\n.*\n(.*)\n/\1/g;b1"

का उपयोग करके &&&ऊपर, हम प्रतिस्थापन के आराम के लिए स्ट्रिंग के मामले पैटर्न का पुन: उपयोग, तो ABcdefसे बदल दिया जाएगा PQrstuVWxऔर AbCdEfकरने के लिए PqRsTuVwX। इसे बदलें &केवल पहले 6 वर्णों के मामले को प्रभावित करने के लिए।

(ध्यान दें कि यह वह नहीं कर सकता जो आप चाहते हैं या एक अनंत लूप में चला सकते हैं यदि प्रतिस्थापन प्रतिस्थापन के अधीन हो सकता है (उदाहरण के fooलिए foo, यदि प्रतिस्थापन के लिए , या इसके bcdलिए abcd)


8

पोर्टेबल समाधान का उपयोग कर awk:

awk -v find=abcdef -v rep=pqrstu '{
  lwr=tolower($0)
  offset=index(lwr, tolower(find))

  if( offset > 0 ) {
    printf "%s", substr($0, 0, offset)
    len=length(find)

    for( i=0; i<len; i++ ) {
      out=substr(rep, i+1, 1)

      if( substr($0, offset+i, 1) == substr(lwr, offset+i, 1) )
        printf "%s", tolower(out)
      else
        printf "%s", toupper(out)
    }

    printf "%s\n", substr($0, offset+len)
  }
}'

उदाहरण इनपुट:

other abcdef other
other Abcdef other
other AbCdEf other

उदाहरण आउटपुट:

other pqrstu other
other Pqrstu other
other PqRsTu other

अपडेट करें

जैसा कि टिप्पणियों में बताया गया है, उपरोक्त केवल findप्रत्येक पंक्ति में पहले उदाहरण को बदल देगा । सभी उदाहरणों को बदलने के लिए:

awk -v find=abcdef -v rep=pqrstu '{
  input=$0
  lwr=tolower(input)
  offset=index(lwr, tolower(find))

  if( offset > 0 ) {
    while( offset > 0 ) {

      printf "%s", substr(input, 0, offset)
      len=length(find)

      for( i=0; i<len; i++ ) {
        out=substr(rep, i+1, 1)

        if( substr(input, offset+i, 1) == substr(lwr, offset+i, 1) )
          printf "%s", tolower(out)
        else
          printf "%s", toupper(out)
      }

      input=substr(input, offset+len)
      lwr=substr(lwr, offset+len)
      offset=index(lwr, tolower(find))
    }

    print input
  }
}'

उदाहरण इनपुट:

other abcdef other ABCdef other
other Abcdef other abcDEF
other AbCdEf other aBCdEf other

उदाहरण आउटपुट:

other pqrstu other PQRstu other
other Pqrstu other pqrSTU
other PqRsTu other pQRsTu other

ध्यान दें कि प्रति पंक्ति केवल एक उदाहरण संसाधित करता है।
स्टीफन चेज़लस

@StephaneChazelas, कई उदाहरणों को संभालने के लिए अद्यतन किया गया।
ग्रीम

6

आप उपयोग कर सकते हैं perl। Faq से सीधे - से उद्धृत perldoc perlfaq6:

RHS पर मामला संरक्षित करते समय मैं LHS पर केस-असंवेदनशील कैसे प्रतिस्थापित करता हूं?

यहाँ लैरी रोसलर द्वारा एक सुंदर Perlish समाधान है। यह ASCII स्ट्रिंग्स पर बिटवाइज़ एक्सर के गुणों का शोषण करता है।

   $_= "this is a TEsT case";

   $old = 'test';
   $new = 'success';

   s{(\Q$old\E)}
   { uc $new | (uc $1 ^ $1) .
           (uc(substr $1, -1) ^ substr $1, -1) x
           (length($new) - length $1)
   }egi;

   print;

और यहाँ यह उप के रूप में है, ऊपर के बाद मॉडलिंग की गई है:

       sub preserve_case($$) {
               my ($old, $new) = @_;
               my $mask = uc $old ^ $old;

               uc $new | $mask .
                       substr($mask, -1) x (length($new) - length($old))
   }

       $string = "this is a TEsT case";
       $string =~ s/(test)/preserve_case($1, "success")/egi;
       print "$string\n";

यह प्रिंट:

           this is a SUcCESS case

एक विकल्प के रूप में, प्रतिस्थापन शब्द के मामले को रखने के लिए यदि यह मूल से अधिक लंबा है, तो आप जेफ पिनयिन द्वारा इस कोड का उपयोग कर सकते हैं:

   sub preserve_case {
           my ($from, $to) = @_;
           my ($lf, $lt) = map length, @_;

           if ($lt < $lf) { $from = substr $from, 0, $lt }
           else { $from .= substr $to, $lf }

           return uc $to | ($from ^ uc $from);
           }

यह "यह एक SUCCess केस है।"

बस यह दिखाने के लिए कि सी प्रोग्रामर किसी भी प्रोग्रामिंग भाषा में सी लिख सकते हैं, यदि आप अधिक सी-लाइक सॉल्यूशन पसंद करते हैं, तो निम्न स्क्रिप्ट प्रतिस्थापन को एक ही मामले, पत्र द्वारा पत्र, मूल के रूप में बनाती है। (यह भी Perlish समाधान से चलाता है के बारे में 240% धीमी गति से होता है।) यदि प्रतिस्थापन में स्ट्रिंग से प्रतिस्थापित किए जाने वाले वर्णों की तुलना में अधिक वर्ण होते हैं, तो अंतिम प्रतिस्थापन के मामले में अंतिम वर्ण का उपयोग किया जाता है।

   # Original by Nathan Torkington, massaged by Jeffrey Friedl
   #
   sub preserve_case($$)
   {
           my ($old, $new) = @_;
           my ($state) = 0; # 0 = no change; 1 = lc; 2 = uc
           my ($i, $oldlen, $newlen, $c) = (0, length($old), length($new));
           my ($len) = $oldlen < $newlen ? $oldlen : $newlen;

           for ($i = 0; $i < $len; $i++) {
                   if ($c = substr($old, $i, 1), $c =~ /[\W\d_]/) {
                           $state = 0;
                   } elsif (lc $c eq $c) {
                           substr($new, $i, 1) = lc(substr($new, $i, 1));
                           $state = 1;
                   } else {
                           substr($new, $i, 1) = uc(substr($new, $i, 1));
                           $state = 2;
                   }
           }
           # finish up with any remaining new (for when new is longer than old)
           if ($newlen > $oldlen) {
                   if ($state == 1) {
                           substr($new, $oldlen) = lc(substr($new, $oldlen));
                   } elsif ($state == 2) {
                           substr($new, $oldlen) = uc(substr($new, $oldlen));
                   }
           }
           return $new;
   }

ध्यान दें कि यह ASCII अक्षरों तक सीमित है।
स्टीफन चेज़लस

5

यदि आप प्रतिस्थापित को ट्रिम करते हैं pqrstu, तो यह प्रयास करें:

इनपुट:

abcdef
Abcdef
AbCdEf
ABcDeF

ouput:

$ perl -lpe 's/$_/$_^lc($_)^"pqrstu"/ei' file
pqrstu
Pqrstu
PqRsTu
PQrStU

यदि आप के साथ प्रतिस्थापित करना चाहते हैं prstuvxyz, तो यह हो सकता है:

$ perl -lne '@c=unpack("(A4)*",$_);
    $_ =~ s/$_/$_^lc($_)^"pqrstu"/ei;
    $c[0] =~ s/$c[0]/$c[0]^lc($c[0])^"vxyz"/ei;
    print $_,$c[0]' file
pqrstuvxyz
PqrstuVxyz
PqRsTuVxYz
PQrStUVXyZ

मैं किसी भी नियम को मैप करने नहीं मिल सकता है ABcDeF-> PQrStUvxyz


ध्यान दें कि यह ASCII अक्षरों तक सीमित है।
स्टीफन चेज़लस

3

कुछ ऐसा होगा जो आपने वर्णित किया है।

sed -i.bak -e "s/abcdef/pqrstuvxyz/g" \
 -e "s/AbCdEf/PqRsTuVxYz/g" \
 -e "s/Abcdef/Pqrstuvxyz/g" files/src
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.