সেড সঙ্গে কেস ম্যাচিং প্যাটার্ন প্রতিস্থাপন


14

আমার বেশ কয়েকটি ফাইল জুড়ে একটি উত্স কোড রয়েছে।

  • এটির একটি প্যাটার্ন রয়েছে abcdefযা আমার সাথে প্রতিস্থাপন করা দরকার pqrstuvxyz
  • প্যাটার্নটি হতে পারে Abcdef(বাক্য কেস) তখন এটি দিয়ে প্রতিস্থাপন করা দরকার Pqrstuvxyz
  • প্যাটার্নটি AbCdEf(টগল কেস) হতে পারে তারপরে এটি প্রতিস্থাপন করা দরকার PqRsTuVxYz

সংক্ষেপে, আমার উত্স প্যাটার্নের কেসটির সাথে মেলে এবং উপযুক্ত গন্তব্য প্যাটার্নটি প্রয়োগ করতে হবে।

আমি কীভাবে এটি sedবা অন্য কোনও সরঞ্জাম ব্যবহার করে এটি অর্জন করতে পারি ?


আর তা হলে ABcDeF?
স্টাফেন চেজেলাস

PQrStUvxyz - আমি আপনার বক্তব্য পেয়েছি।
ব্যবহারকারী 1263746

সুতরাং ABcDeF-> PQrStUvxyzতবে অবশ্যই AbCdEf-> PqRsTuvxyzযৌক্তিকভাবে সামঞ্জস্যপূর্ণ হবে। কেসটি যদি একটি স্ট্রিং থেকে অন্য স্ট্রিংয়ে অনুলিপি করা হয় তবে দ্বিতীয় প্রতিস্থাপনের স্ট্রিং দীর্ঘ হলে কী হবে should
গ্রিম

ভাল ব্রাভিটির স্বার্থে "pqrstu" এর প্রতিস্থাপনটি ছাঁটাতে দিন।
ব্যবহারকারী 1263746

উত্তর:


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'

জিএনইউ সেডের সাহায্যে এটি কিছুটা সহজ:

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

দ্রষ্টব্য যে প্রতি লাইনে কেবল একটি উদাহরণ প্রক্রিয়া করে।
স্টাফেন চেজেলাস

একাধিক ঘটনা পরিচালনা করার জন্য আপডেট করা হয়েছে স্টেফেনচেজেলাস।
গ্রিম

6

আপনি ব্যবহার করতে পারে perl। সোজা প্রশ্ন থেকে - উদ্ধৃতperldoc perlfaq6 :

আরএইচএসে কেস সংরক্ষণের সময় আমি কীভাবে এলএইচএসের উপর সংবেদনশীলভাবে কেস প্রতিস্থাপন করব?

ল্যারি রোসলারের একটি সুন্দর পার্লিশ সমাধান এখানে। এটি 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);
           }

এটি বাক্যটিকে "এটি একটি সুইস কেস" হিসাবে পরিবর্তন করে।

কেবল সি প্রোগ্রামাররা যে কোনও প্রোগ্রামিং ভাষায় সি লিখতে পারে তা দেখানোর জন্য, আপনি যদি আরও সি-জাতীয় সমাধান পছন্দ করেন তবে নিম্নলিখিত স্ক্রিপ্টটি মূল হিসাবে চিঠির মাধ্যমে চিঠিপত্রের মতো একই ক্ষেত্রে তৈরি করে। (পার্লিশ সমাধানের চেয়ে প্রায় 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
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.