এক সাথে এক সাথে একাধিক নিদর্শন প্রতিস্থাপন কিভাবে?


231

ধরুন আমার কাছে 'abbc' স্ট্রিং রয়েছে এবং আমি প্রতিস্থাপন করতে চাই:

  • ab -> বিসি
  • বিসি -> আব

আমি যদি দুটি প্রতিস্থাপনের চেষ্টা করি তবে ফলাফলটি আমি যা চাই তা তা নয়:

echo 'abbc' | sed 's/ab/bc/g;s/bc/ab/g'
abab

সুতরাং নীচের মত প্রতিস্থাপনের জন্য আমি কোন সেড কমান্ডটি ব্যবহার করতে পারি?

echo abbc | sed SED_COMMAND
bcab

সম্পাদনা : পাঠ্যটিতে 2 টিরও বেশি নিদর্শন থাকতে পারে এবং আমি জানি না আমার কতগুলি প্রতিস্থাপনের প্রয়োজন হবে। যেহেতু এখানে একটি উত্তর ছিল sedযা একটি স্ট্রিম সম্পাদক এবং এর প্রতিস্থাপনগুলি লোভজনকভাবে আমি মনে করি যে এর জন্য আমার কিছু স্ক্রিপ্ট ভাষা ব্যবহার করা প্রয়োজন।


আপনার কি একই লাইনে একাধিক প্রতিস্থাপন করা দরকার? এই gদুটি s///আদেশ থেকে কেবল পতাকাটি না ফেলে দিলে এবং এটি কার্যকর হবে।
ইটান রেইজনার

আপনি আমার প্রশ্নের বিন্দু মিস করেছেন। আমি বোঝাতে চাইছি আপনাকে প্রতি লাইনে একই লাইনে একাধিকবার প্রতিস্থাপন করা দরকার । মূল ইনপুটটির জন্য ab বা একাধিক ম্যাচ আছে কি bc?
এটান রেইজনার

দুঃখিত @ এটানরেইজনার আমি ভুল বুঝেছি, আনসার হ্যাঁ। পাঠ্যের একাধিক প্রতিস্থাপন থাকতে পারে।
ড্যানিলোএনসি

উত্তর:


342

এরকম কিছু হতে পারে:

sed 's/ab/~~/g; s/bc/ab/g; s/~~/bc/g'

~এমন একটি চরিত্রের সাথে প্রতিস্থাপন করুন যা আপনি জানেন যে স্ট্রিংটিতে থাকবে না।


9
গনুহ হ্যান্ডলগুলি nuls কিন্তু, তাই আপনি ব্যবহার করতে পারেন \x0জন্য ~~
jthill

3
Is gপ্রয়োজনীয় এবং এটা কি কাজ করে?
লি

12
@ লি gগ্লোবাল জন্য - এটি প্রতিটি লাইনে সমস্ত প্যাটার্নের প্রতিস্থাপন করে কেবল প্রথম (যা পূর্বনির্ধারিত আচরণ) এর পরিবর্তে।
nnot101

1
আমার উত্তর দেখার stackoverflow.com/a/41273117/539149 ooga ব্যবস্থাপকের জবাবেরই একটা প্রকরণ একাধিক সমন্বয় একযোগে প্রতিস্থাপন করতে পারেন জন্য।
জ্যাক মরিস

3
আপনি জানেন যে উত্পাদন কোডের জন্য স্ট্রিংটিতে থাকবে না , ইনপুট সম্পর্কে কখনও কোনও অনুমান করবেন না। পরীক্ষাগুলির জন্য, ভাল, পরীক্ষাগুলি কখনই সত্যতা প্রমাণ করে না, তবে পরীক্ষার জন্য একটি ভাল ধারণা হ'ল: স্ক্রিপ্টটি নিজেই ইনপুট হিসাবে ব্যবহার করুন।
হ্যগেলো

33

আমি সর্বদা "-e" এর সাথে একাধিক বিবৃতি ব্যবহার করি

$ sed -e 's:AND:\n&:g' -e 's:GROUP BY:\n&:g' -e 's:UNION:\n&:g' -e 's:FROM:\n&:g' file > readable.sql

এটি সমস্ত এবং এর আগে গ্রুপ, ইউনিয়ন এবং ফরাস এর আগে একটি '\ n' যুক্ত করবে, যদিও '&' এর অর্থ ম্যাচিং স্ট্রিং এবং '\ n &' এর অর্থ আপনি 'ম্যাচিংয়ের আগে' \ n 'দিয়ে ম্যাচিং স্ট্রিং প্রতিস্থাপন করতে চান '


14

ওগা জবাবের এখানে একটি ভিন্নতা যা একাধিক অনুসন্ধানের জন্য কাজ করে এবং কীভাবে মানগুলি পুনরায় ব্যবহৃত হতে পারে তা যাচাই না করে জোড়া জোড়া প্রতিস্থাপন করে:

sed -i '
s/\bAB\b/________BC________/g
s/\bBC\b/________CD________/g
s/________//g
' path_to_your_files/*.txt

এখানে একটি উদাহরণ:

আগে:

some text AB some more text "BC" and more text.

পরে:

some text BC some more text "CD" and more text.

নোট করুন \bশব্দের সীমানা বোঝায় যা ________অনুসন্ধানে হস্তক্ষেপ থেকে বাধা দেয় (আমি উবুন্টুতে জিএনইউ সেড ৪.২.২ ব্যবহার করছি)। আপনি যদি কোনও শব্দ সীমানা অনুসন্ধান ব্যবহার না করে থাকেন তবে এই কৌশলটি কাজ করতে পারে না।

এছাড়াও নোট করুন যে এটি কমান্ডের শেষে s/________//gএবং অপসারণের সমান ফলাফল দেয় তবে && sed -i 's/________//g' path_to_your_files/*.txtদু'বার পথ নির্দিষ্ট করার প্রয়োজন হয় না।

জেথিলের পরামর্শ অনুসারে এটি ব্যবহারের ক্ষেত্রে \x0বা তার _\x0_পরিবর্তে ________যদি আপনি জানেন যে আপনার ফাইলগুলিতে কোনও নাল উপস্থিত না হয় তবে এটির ক্ষেত্রে একটি সাধারণ তারতম্য ।


ইনপুট কী থাকতে পারে সে সম্পর্কে অনুমান না করা সম্পর্কে আমি উপরোক্ত হাজেলোর মন্তব্যের সাথে একমত। অতএব, আমি ব্যক্তিগতভাবে অনুভব করি যে একে অপরের শীর্ষে পাইপিং সেডগুলি বাদ দিয়ে এটি সবচেয়ে নির্ভরযোগ্য সমাধান ( sed 's/ab/xy/' | sed 's/cd/ab/' .....)
লেটব্যাকুন

12

sedএকটি স্ট্রিম সম্পাদক is এটি লোভের সাথে অনুসন্ধান করে এবং প্রতিস্থাপন করে। আপনি যা চেয়েছিলেন তা করার একমাত্র উপায় হ'ল মধ্যবর্তী প্রতিস্থাপনের প্যাটার্নটি ব্যবহার করা এবং এটি শেষে ফিরে আসা।

echo 'abcd' | sed -e 's/ab/xy/;s/cd/ab/;s/xy/cd/'


4

এটি আপনার (জিএনইউ সেড) কাজ করতে পারে:

sed -r '1{x;s/^/:abbc:bcab/;x};G;s/^/\n/;:a;/\n\n/{P;d};s/\n(ab|bc)(.*\n.*:(\1)([^:]*))/\4\n\2/;ta;s/\n(.)/\1\n/;ta' file

এটি এমন একটি দেখার সারণী ব্যবহার করে যা হোল্ড স্পেসে (এইচএস) প্রস্তুত এবং অনুষ্ঠিত হয় এবং তারপরে প্রতিটি লাইনে সংযুক্ত থাকে। একটি অনন্য চিহ্নিতকারী ( \nএক্ষেত্রে) লাইনটি শুরু করার জন্য প্রস্তুত করা হয়েছে এবং লাইনের দৈর্ঘ্য জুড়ে অনুসন্ধানের সাথে ধাক্কা দেওয়ার পদ্ধতি হিসাবে ব্যবহৃত হয়। চিহ্নিতকারী একবার লাইনের শেষ প্রান্তে পৌঁছালে প্রক্রিয়াটি শেষ হয়ে যায় এবং লুকিং টেবিলটি প্রিন্ট করা হয় এবং চিহ্নিতকারীগুলি ফেলে দেওয়া হয়।

এনবি লুকিং টেবিলটি একেবারে শুরুতে প্রথম স্থানে :রয়েছে এবং বিকল্পের স্ট্রিংগুলির সাথে সংঘাত না হওয়ার জন্য দ্বিতীয় একটি অনন্য মার্কার (এই ক্ষেত্রে ) বেছে নেওয়া হয়েছে।

কিছু মন্তব্য সহ:

sed -r '
  # initialize hold with :abbc:bcab
  1 {
    x
    s/^/:abbc:bcab/
    x
  }

  G        # append hold to patt (after a \n)

  s/^/\n/  # prepend a \n

  :a

  /\n\n/ {
    P      # print patt up to first \n
    d      # delete patt & start next cycle
  }

  s/\n(ab|bc)(.*\n.*:(\1)([^:]*))/\4\n\2/
  ta       # goto a if sub occurred

  s/\n(.)/\1\n/  # move one char past the first \n
  ta       # goto a if sub occurred
'

টেবিলটি এভাবে কাজ করে:

   **   **   replacement
:abbc:bcab
 **   **     pattern

3

একক প্যাটার্ন সংঘটনগুলির জন্য একটি সহজ পদ্ধতির হতে পারে আপনি নীচের মতো চেষ্টা করতে পারেন: প্রতিধ্বনি 'abbc' | সেড 'এস / আব / বিসি /; এস / বিসি / এ্যাব / 2'

আমার আউটপুট:

 ~# echo 'abbc' | sed 's/ab/bc/;s/bc/ab/2'
 bcab

প্যাটার্নের একাধিক ঘটনার জন্য:

sed 's/\(ab\)\(bc\)/\2\1/g'

উদাহরণ

~# cat try.txt
abbc abbc abbc
bcab abbc bcab
abbc abbc bcab

~# sed 's/\(ab\)\(bc\)/\2\1/g' try.txt
bcab bcab bcab
bcab bcab bcab
bcab bcab bcab

আশাকরি এটা সাহায্য করবে !!


2

TCL টি builtin এই জন্য

$ tclsh
% string map {ab bc bc ab} abbc
bcab

এটি বর্তমান অবস্থান থেকে শুরু করে স্ট্রিং তুলনা করে স্ট্রিংকে একটি চরিত্রের হাঁটা দিয়ে কাজ করে।

পার্ল ইন:

perl -E '
    sub string_map {
        my ($str, %map) = @_;
        my $i = 0;
        while ($i < length $str) {
          KEYS:
            for my $key (keys %map) {
                if (substr($str, $i, length $key) eq $key) {
                    substr($str, $i, length $key) = $map{$key};
                    $i += length($map{$key}) - 1;
                    last KEYS;
                }
            }
            $i++;
        }
        return $str;
    }
    say string_map("abbc", "ab"=>"bc", "bc"=>"ab");
'
bcab

0

এখানে awkওগাস উপর ভিত্তি করেsed

echo 'abbc' | awk '{gsub(/ab/,"xy");gsub(/bc/,"ab");gsub(/xy/,"bc")}1'
bcab
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.