এসইডি রেজেক্সের সাথে অ-লোভী মিল (ইমুলেট পারল'স? *?)


22

আমি sedপ্রথম ABএবং প্রথম সংঘটিত AC(অন্তর্ভুক্ত) এর মধ্যে একটি স্ট্রিংয়ের মধ্যে যে কোনও কিছু প্রতিস্থাপন করতে ব্যবহার করতে চাই XXX

জন্য উদাহরণস্বরূপ , আমি এই স্ট্রিং আছে (এই স্ট্রিং শুধুমাত্র একটি পরীক্ষার জন্য হয়):

ssABteAstACABnnACss

এবং আমি এই অনুরূপ আউটপুট চাই: ssXXXABnnACss


আমি এটি দিয়ে perl:

$ echo 'ssABteAstACABnnACss' | perl -pe 's/AB.*?AC/XXX/'
ssXXXABnnACss

কিন্তু আমি সঙ্গে এটি বাস্তবায়ন করতে চান sed। নিম্নলিখিত (পার্ল-সামঞ্জস্যপূর্ণ রেজেক্স ব্যবহার করে) কাজ করে না:

$ echo 'ssABteAstACABnnACss' | sed -re 's/AB.*?AC/XXX/'
ssXXXss

2
এটা কোন মানে নেই। পার্লে আপনার একটি কার্যকরী সমাধান রয়েছে তবে আপনি শেড ব্যবহার করতে চান কেন?
কুসালানন্দ

উত্তর:


16

সবচেয়ে দীর্ঘতম ম্যাচটি শেড রেজেক্সেসের সাথে মেলে। শেডের অ-লোভীর সমতুল্য নেই।

স্পষ্টতই আমরা যা করতে চাই তা হ'ল ম্যাচ

  1. AB,
    অনুসরণ করে
  2. কিছু যে কোন পরিমাণ ব্যতীত অন্য AC,
    দ্বারা অনুসরণ
  3. AC

দুর্ভাগ্যক্রমে, sed# 2 করতে পারবেন না - কমপক্ষে একটি বহু-চরিত্রের নিয়মিত প্রকাশের জন্য নয়। অবশ্যই, একটি একক চরিত্রের নিয়মিত প্রকাশের জন্য যেমন @(বা এমনকি [123]), আমরা করতে পারি [^@]*বা করতে পারি [^123]*। এবং তাই আমরা সেডের সীমাবদ্ধতাগুলি ঘিরে কাজ করতে পারি সমস্ত ক্ষেত্রে উপস্থিতি পরিবর্তন ACকরে @এবং তারপরে অনুসন্ধান করে

  1. AB,
    অনুসরণ করে
  2. ছাড়া আর কিছু যে কোন সংখ্যার @,
    দ্বারা অনুসরণ
  3. @

এটার মত:

sed 's/AC/@/g; s/AB[^@]*@/XXX/; s/@/AC/g'

শেষ অংশটি @ফিরে যাওয়ার নজিরবিহীন দৃষ্টান্তগুলিকে পরিবর্তন করে AC

তবে অবশ্যই এটি একটি বেপরোয়া পন্থা, কারণ ইনপুটটিতে ইতিমধ্যে @অক্ষর থাকতে পারে , তাই তাদের মিলিয়ে আমরা মিথ্যা ধনাত্মকতা পেতে পারি। যাইহোক, যেহেতু কোনও শেল ভেরিয়েবলের মধ্যে কোনও NUL ( \x00) অক্ষর থাকবে না, NUL সম্ভবত উপরের কাজের আশেপাশে ব্যবহার করার জন্য একটি ভাল চরিত্র @:

$ echo 'ssABteAstACABnnACss' | sed 's/AC/\x00/g; s/AB[^\x00]*\x00/XXX/; s/\x00/AC/g'
ssXXXABnnACss

NUL এর ব্যবহারের জন্য GNU সেড প্রয়োজন। (জিএনইউ বৈশিষ্ট্যগুলি সক্ষম রয়েছে তা নিশ্চিত করার জন্য, ব্যবহারকারীকে অবশ্যই শেল ভেরিয়েবল POSIXLY_CORRECT সেট করা উচিত নয়))

আপনি যদি -zএনএনএল-বিচ্ছিন্ন ইনপুট যেমন আউটপুট হ্যান্ডেল করতে জিএনইউ পতাকা ব্যবহার করে সেড ব্যবহার করছেন find ... -print0তবে NUL প্যাটার্ন স্পেসে থাকবে না এবং এখানে বিকল্পের জন্য NUL ভাল পছন্দ।

যদিও NUL ব্যাশ ভেরিয়েবলে থাকতে পারে না, এটি printfকমান্ডে অন্তর্ভুক্ত করা সম্ভব । যদি আপনার ইনপুট স্ট্রিংটিতে NUL সহ মোটে কোনও অক্ষর থাকতে পারে, তবে স্টাফেন চেজেলাসের উত্তরটি দেখুন যা একটি চালাক পালানোর পদ্ধতি যোগ করে।


একটি দীর্ঘ ব্যাখ্যা যুক্ত করতে আমি আপনার উত্তরটি সম্পাদনা করেছি; এটিকে ছাঁটাই করতে বা এটিকে আবার ঘোরান free
জি-ম্যান বলছেন 'মনিকা পুনরায় ইনস্টল করুন'

@ জি-ম্যান এটি একটি দুর্দান্ত ব্যাখ্যা! খুব সুন্দরভাবে সম্পন্ন হয়েছে। ধন্যবাদ.
1024

আপনি echoবা printfএকটি `\ 000 'ঠিক পরিমাণে জরিমানা করতে পারেন (বা ইনপুটটি কোনও ফাইল থেকে আসতে পারে)। তবে সাধারণভাবে, পাঠ্যের একটি স্ট্রিং অবশ্যই অবশ্যই NUL না থাকে have
ইল্কাচ্চু

@ ইলক্কাছু আপনি ঠিক সে সম্পর্কেই বলেছেন। আমার যা লেখা উচিত তা হ'ল কোনও শেল ভেরিয়েবল বা প্যারামিটারে NULs থাকতে পারে না। উত্তর আপডেট হয়েছে।
1024

আপনি যদি আবার ফিরে ACযান AC@এবং ফিরে যান তবে এটি কি পুরোপুরি নিরাপদ হবে না?
মাইকেল Vehrs

7

কিছু sedবাস্তবায়নের পক্ষে এর সমর্থন রয়েছে। ssedএকটি পিসিআরই মোড আছে:

ssed -R 's/AB.*?AC/XXX/g'

বর্ধিত রিজেক্সপস ব্যবহার করার সময় এটি অ্যান্ড টি এস্ট সিডের সংমিশ্রণ এবং অবহেলা রয়েছে :

sed -A 's/AB(.*&(.*AC.*)!)AC/XXX/g'

বহনযোগ্যভাবে, আপনি এই কৌশলটি ব্যবহার করতে পারেন: শেষ স্ট্রিংটি (এখানে AC) এমন একক অক্ষর দ্বারা প্রতিস্থাপন করুন যা শুরু বা শেষের স্ট্রিংয়ের মধ্যে ঘটে না (যেমন :এখানে) আপনি করতে পারেন s/AB[^:]*://, এবং যদি অক্ষরটি ইনপুটটিতে উপস্থিত হতে পারে , একটি পালানোর প্রক্রিয়া ব্যবহার করুন যা শুরু এবং শেষের স্ট্রিংগুলির সাথে সংঘর্ষ না করে।

একটি উদাহরণ:

sed 's/_/_u/g; # use _ as the escape character, escape it
     s/:/_c/g; # escape our replacement character
     s/AC/:/g; # replace the end string
     s/AB[^:]*:/XXX/g; # actual replacement
     s/:/AC/g; # restore the remaining end strings
     s/_c/:/g; # revert escaping
     s/_u/_/g'

জিএনইউ সহ sed, একটি পদ্ধতির প্রতিস্থাপনের অক্ষর হিসাবে নতুন লাইন ব্যবহার করা। যেহেতু sedএকবারে এক লাইন প্রক্রিয়া করে, প্যাটার্ন স্পেসে নিউলাইন কখনই আসে না, তাই কেউ এটি করতে পারেন:

sed 's/AC/\n/g;s/AB[^\n]*\n/XXX/g;s/\n/AC/g'

এটি সাধারণত অন্যান্য sedপ্রয়োগের সাথে কাজ করে না কারণ তারা সমর্থন করে না [^\n]। গনুহ সঙ্গে sedআপনি কি নিশ্চিত যে POSIX সামঞ্জস্য সক্রিয় করা হয় না (POSIXLY_CORRECT এনভায়রনমেন্ট ভেরিয়েবল সঙ্গে মত) করা আছে।


6

না, সেড রেজেক্সগুলির অ-লোভী মিল নেই।

পার্লের মতো একই কাজ করে এমন AC"কিছুই না থাকা AC" ব্যবহার করে আপনি প্রথম পাঠ্যটির সাথে মিলিয়ে যেতে পারেন । বিষয়টি হ'ল, "যা কিছু নেই সেগুলি" একটি নিয়মিত প্রকাশ হিসাবে সহজে প্রকাশ করা যায় না: একটি নিয়মিত প্রকাশ থাকে যা নিয়মিত প্রকাশের তাত্পর্যকে স্বীকৃতি দেয় তবে নেগ্রেশন রেজেেক্স দ্রুত জটিল হয়। এবং পোর্টেবল সেডে, এটি মোটেও সম্ভব নয়, কারণ নেগ্রেশন রিজেক্সের এমন একটি বিকল্পকে গোষ্ঠীকরণের প্রয়োজন যা বর্ধিত নিয়মিত এক্সপ্রেশনগুলিতে উপস্থিত থাকে (উদাহরণস্বরূপ অবাক) তবে বহনযোগ্য বেসিক নিয়মিত এক্সপ্রেশনগুলিতে নয়। সিএনডি এর কিছু সংস্করণ যেমন জিএনইউ সেডের বিআরই-তে এক্সটেনশন রয়েছে যা এটি সমস্ত সম্ভাব্য নিয়মিত অভিব্যক্তি প্রকাশ করতে সক্ষম করে।AC.*?ACAC

sed 's/AB\([^A]*\|A[^C]\)*A*AC/XXX/'

একটি রেজেক্সকে অগ্রাহ্য করার অসুবিধার কারণে, এটি ভালভাবে কার্যকর হয় না। পরিবর্তে আপনি যা করতে পারেন তা হ'ল অস্থায়ীভাবে লাইনের রূপান্তর। কিছু সেড বাস্তবায়নে, আপনি একটি চিহ্নকার হিসাবে নিউলাইনগুলি ব্যবহার করতে পারেন, যেহেতু তারা কোনও ইনপুট লাইনে উপস্থিত হতে পারে না (এবং যদি আপনার একাধিক মার্কার প্রয়োজন হয়, তবে একটি ভিন্ন চরিত্রের পরে নিউলাইন ব্যবহার করুন)।

sed -e 's/AC/\
&/g' -e 's/AB[^\
]*\nAC/XXX/' -e 's/\n//g'

তবে সাবধান থাকুন যে ব্যাকস্ল্যাশ-নিউলাইনটি কিছু সেড সংস্করণ সহ একটি অক্ষর সেটগুলিতে কাজ করে না। বিশেষত, এটি জিএনইউ সেডে কাজ করে না, এটি নন-এমবেডড লিনাক্সের সেড বাস্তবায়ন; জিএনইউ সেডে আপনি এর \nপরিবর্তে ব্যবহার করতে পারেন :

sed -e 's/AC/\
&/g' -e 's/AB[^\n]*\nAC/XXX/' -e 's/\n//g'

এই নির্দিষ্ট ক্ষেত্রে, এটি ACএকটি নতুন লাইন দ্বারা প্রথম প্রতিস্থাপন যথেষ্ট । আমি উপরে উপস্থাপনা পদ্ধতির আরো সাধারণ।

শেডে আরও শক্তিশালী পদ্ধতির হ'ল হোল্ড স্পেসে লাইনটি সংরক্ষণ করা, লাইনটির প্রথম "আকর্ষণীয়" অংশ বাদে সমস্ত অপসারণ, হোল্ড স্পেস এবং প্যাটার্ন স্পেস এক্সচেঞ্জ করা বা হোল্ড স্পেসে প্যাটার্ন স্পেস যুক্ত করা এবং পুনরাবৃত্তি করা। যাইহোক, আপনি যদি এই জটিল জিনিসগুলি করতে শুরু করেন তবে আপনার সত্যিকার অর্থে বিশ্রীতে চলে যাওয়ার বিষয়ে চিন্তা করা উচিত। ওওকের সাথে অ-লোভী মিলও নেই, তবে আপনি একটি স্ট্রিং বিভক্ত করতে পারেন এবং অংশগুলিকে ভেরিয়েবলগুলিতে সংরক্ষণ করতে পারেন।


@ ইলক্কাছু না, তা হয় না। s/\n//gসমস্ত নতুনলাইন সরিয়ে দেয়।
গিলস 'অসন্তুষ্ট হওয়া বন্ধ করুন'

asdf ও ডিফেন্ডার। ঠিক আছে, আমার খারাপ।
ইল্কাচ্চু

3

সেড - ক্রিস্টোফ সিগার্টের অ-লোভী মিল

সেডে লোভনীয় মিল না পাওয়ার কৌশলটি ম্যাচটি বন্ধ করে দেওয়া একটি বাদ দিয়ে সমস্ত চরিত্রের সাথে মেলে। আমি জানি, একজন নন-ব্রেইনার, তবে আমি এতে মূল্যবান মিনিট নষ্ট করেছি এবং শেল স্ক্রিপ্টগুলি সর্বোপরি দ্রুত এবং সহজ হওয়া উচিত। সুতরাং অন্য কারও প্রয়োজন হতে পারে:

লোভী মিলছে

% echo "<b>foo</b>bar" | sed 's/<.*>//g'
bar

লোভী মিল নেই

% echo "<b>foo</b>bar" | sed 's/<[^>]*>//g'
foobar


3
"নো-ব্রেইনার" শব্দটি অস্পষ্ট। এই ক্ষেত্রে, এটি পরিষ্কার নয় যে আপনি (বা ক্রিস্টোফ সিগার্ট) এর মাধ্যমে এটি ভেবেছিলেন। বিশেষত, যদি আপনি প্রশ্নের সুনির্দিষ্ট সমস্যাটি কীভাবে সমাধান করতে হয় তবে (যেখানে শূন্য-এর-বেশি-প্রকাশের একাধিক চরিত্র অনুসরণ করা হয় ) তা যদি ভাল হয় তবে তা ভাল হত । আপনি দেখতে পাবেন যে এই উত্তরটি সেক্ষেত্রে ভাল কাজ করে না।
স্কট

খরগোশের গর্তটি আমার কাছে প্রথম নজরে দেখে মনে হয়েছিল তার চেয়ে অনেক গভীর। আপনি ঠিক বলেছেন, বহু-চরিত্রের নিয়মিত অভিব্যক্তির জন্য এই কর্মটি কার্যকরভাবে কাজ করে না।
gresolio

0

আপনার ক্ষেত্রে আপনি এইভাবে ক্লোরিং চরটি উপেক্ষা করতে পারেন:

echo 'ssABteAstACABnnACss' | sed 's/AB[^C]*AC/XXX/'

2
প্রশ্নটি বলে, "আমি … ABএর ACসাথে প্রথম এবং প্রথম ঘটনার মধ্যে যে কোনও কিছু প্রতিস্থাপন করতে চাই XXX" এবং উদাহরণ ইনপুট ssABteAstACABnnACssহিসাবে দেয় । এই উত্তরটি উদাহরণ হিসাবে কাজ করে, তবে সাধারণভাবে প্রশ্নের উত্তর দেয় না। উদাহরণস্বরূপ, আউটপুটও পাওয়া উচিত , তবে আপনার কমান্ড অপরিবর্তিত হয়ে এই লাইনটি অতিক্রম করবে। ssABteCstACABnnACssaaXXXABnnACss
জি-ম্যান বলছেন 'পুনরায় ইনস্টল করুন মনিকা'

0

সমাধানটি বেশ সহজ। .*লোভী, তবে এটি একেবারে লোভী নয়। ssABteAstACABnnACssRegexp এর সাথে মিলের কথা বিবেচনা করুন AB.*ACACযে অনুসরণ করে .*আবশ্যক আসলে একটি ম্যাচ আছে। সমস্যাটি হ'ল কারণ .*লোভী, পরবর্তীটি প্রথমটির চেয়ে শেষের সাথেAC মিলবে । রিগ এক্সএক্সে আক্ষরিক ssABteAstACABnn এসি এসএস- এ শেষের সাথে মেলে যখন প্রথমটি খায় । এটি থেকে রোধ করার জন্য, প্রথমটিকে একেবারে দ্বিতীয় এবং অন্য কিছু থেকে আলাদা করার জন্য হাস্যকর কিছু দিয়ে কেবল স্থানান্তর করুন । AC.*ACACAC

echo ssABteAstACABnnACss | sed 's/AC/-foobar-/; s/AB.*-foobar-/XXX/'
ssXXXABnnACss

লোভী .*এখন -foobar-ইন এর পাদদেশে থামবে ssABteAst-foobar-ABnnACssকারণ এগুলি -foobar-ব্যতীত অন্য কোনও নেই -foobar-, এবং রেজিপ্লেক্সের একটি মিল থাকতে -foobar- হবে । পূর্ববর্তী সমস্যাটি ছিল রিজেক্সেপের ACদুটি ম্যাচ .*ছিল তবে লোভী হওয়ায় শেষ ম্যাচটি ACনির্বাচিত হয়েছিল। তবে, এর সাথে -foobar-কেবল একটি ম্যাচ সম্ভব এবং এই ম্যাচটি প্রমাণ করে যে .*একেবারে লোভী নয়। জন্য বাস স্টপ .*ঘটে যেখানে শুধুমাত্র এক ম্যাচ নিম্নলিখিত regexp বাকি জন্য রয়ে যায় .*

মনে রাখবেন যে সমাধানটি ACপ্রথমে উপস্থিত হলে এই ব্যর্থ হবে ABকারণ ACভুলটি প্রতিস্থাপন করা হবে -foobar-। উদাহরণস্বরূপ, প্রথম sedপ্রতিস্থাপনের পরে , ACssABteAstACABnnACssহয়ে যায় -foobar-ssABteAstACABnnACss; অতএব, এর বিরুদ্ধে কোনও মিল খুঁজে পাওয়া যায় না AB.*-foobar-। তবে, যদি ক্রমটি সর্বদা ... এবি ... এসি ... এবি ... এসি ... হয় তবে এই সমাধানটি সফল হবে।


0

একটি বিকল্প স্ট্রিং পরিবর্তন করা যাতে আপনি লোভী মিলটি চান

echo "ssABtCeCAstACABnnACss" | rev | sed -E "s/(.*)CA.*BA(.*)/\1CA+-+-+-+-BA\2/" | rev

ব্যবহার করুন revস্ট্রিং বিপরীত, আপনার ম্যাচ মানদণ্ড, ব্যবহার বিপরীত sedস্বাভাবিক ফ্যাশন এবং তারপর ফলাফলের বিপরীত ....

ssAB-+-+-+-+ACABnnACss
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.