নতুন লাইনের অক্ষরযুক্ত স্ট্রিং প্রতিস্থাপন করুন


10

সঙ্গে bashনিম্নলিখিত বেশী মত সারি দিয়ে শেল, একটি ফাইলে

first "line"
<second>line and so on

আমি এক বা একাধিক ঘটনার প্রতিস্থাপন করতে চাই "line"\n<second>সঙ্গে other charactersএবং প্রতিটি সময় প্রাপ্ত:

first other characters line and so on

সুতরাং আমি একটি স্ট্রিং উভয় বিশেষ অক্ষর যেমন "এবং <এবং একটি নতুন লাইন অক্ষর সঙ্গে প্রতিস্থাপন করতে হবে ।

অন্যান্য উত্তরগুলির মধ্যে অনুসন্ধানের পরে, আমি দেখতে পেলাম যে sedকমান্ডের ডানদিকে (তাই, other charactersস্ট্রিং) নতুন লাইনগুলি গ্রহণ করতে পারে , তবে বামদিকে নয়।

একটি উপায় আছে (তুলনায় সহজ এই ) সঙ্গে এই ফলাফল প্রাপ্ত করার sedবা grep?


আপনি কি ডাব্লু / ম্যাক কাজ করছেন? আপনি যে \newline বিবৃতি দেন তা কেন আমি জিজ্ঞাসা করি। লোকেরা খুব কমই জিজ্ঞাসা করে যে তারা s//\n/জিএনইউ দিয়ে আপনি যেমনটা করতে পারেন তেমন করতে পারেন কিনা sed, যদিও অন্য বেশিরভাগই sedডান হাতের দিক থেকে এই পাল্টা প্রত্যাখ্যান করবেন। তবুও, \nপালানো কোনও sedপসিক্সের বাম দিকে কাজ করবে এবং আপনি তাদের পোর্টেবল করে অনুবাদ করতে পারবেন y/c/\n/যদিও এটির মতো একই প্রভাব থাকবে s/c/\n/gএবং তাই সর্বদা কার্যকর নয়।
মাইক্রজারভ

উত্তর:


3

তিনটি পৃথক sedকমান্ড:

sed '$!N;s/"[^"]*"\n<[^>]*>/other characters /;P;D'

sed -e :n -e '$!N;s/"[^"]*"\n<[^>]*>/other characters /;tn'

sed -e :n -e '$!N;/"$/{$!bn' -e '};s/"[^"]*"\n<[^>]*>/other characters /g'

তারা তিনটিই বেসিক s///ওবস্টিটিউশন কমান্ডটি তৈরি করে :

s/"[^"]*"\n<[^>]*>/other characters /

তারা সকলেই সর্বশেষ পংক্তিটি পরিচালনা করার ক্ষেত্রে যত্ন নেওয়ার চেষ্টা করে, কেননা sedপ্রান্তের ক্ষেত্রে তাদের আউটপুটটিতে ভিন্নতা রয়েছে। এই অর্থ $!যা প্রতি লাইন যে মিলে একটি ঠিকানা থাকে !না $শেষ সময়।

তারা সকলেই Nএকটি \nই- লাইন চরিত্রের অনুসরণ করে পরবর্তী ইনপুট লাইনটি প্যাটার্ন স্পেসে যুক্ত করতে অতিরিক্ত কমান্ডটি ব্যবহার করে । যে কেউ কিছু sedসময়ের জন্য \nইঙ্গিত করে চলেছে সে ইভলাইন চরিত্রের উপর নির্ভর করতে শিখবে - কারণ একটি পাওয়ার একমাত্র উপায় হ'ল এটি স্পষ্টভাবে সেখানে রাখা।

তিনটিই পদক্ষেপ নেওয়ার আগে যতটা সম্ভব সংক্ষিপ্ত ইনপুটটিতে পড়ার জন্য কিছু চেষ্টা করে - sedএটি করার আগে যত তাড়াতাড়ি সম্ভব পুরো ইনপুট ফাইলে না পড়ার দরকার পড়ে।

যদিও তারা সব কিছু করে N, তারা তিনটিই তাদের পুনরাবৃত্তির পদ্ধতিগুলির মধ্যে পৃথক।

প্রথম কমান্ড

প্রথম কমান্ড একটি খুব সাধারণ N;P;Dলুপ নিয়োগ করে । এই তিনটি কমান্ড কোনও পসিক্স-সামঞ্জস্যপূর্ণভাবে অন্তর্নির্মিত sedএবং এগুলি একে অপরকে সুন্দরভাবে পরিপূরক করে।

  • N- যেমনটি ইতিমধ্যে উল্লিখিত হয়েছে, Nসন্নিবেশ করা \nইওলাইন ডিলিমিটারের পরে প্যাটার্ন-স্পেসে এক্সপুট ইনপুট লাইনটি যুক্ত করে ।
  • P- মত p; এটি Pপ্যাটার্ন-স্পেসটি মুদ্রণ করে - তবে কেবলমাত্র প্রথমটি ঘটে যাওয়া \nইওলাইন চরিত্রটি। এবং সুতরাং, নিম্নলিখিত ইনপুট / আদেশ দেওয়া:

    • printf %s\\n one two | sed '$!N;P;d'
  • sed Pখালি একটাই । তবে, সাথে ...

  • D- মত d; এটি Dপ্যাটার্ন-স্পেসকে একাদশ করে এবং আর একটি লাইন-চক্র শুরু করে। বিপরীতে d , প্যাটার্ন-স্পেসে কেবলমাত্র Dপ্রথমটি ঘটে যাওয়া \nইওলাইন পর্যন্ত মুছবে। যদি \nইলাইন চরিত্রের অনুসরণ করে প্যাটার্ন-স্পেসে আরও থাকে sedতবে পরবর্তী লাইনের চক্রটি যা থাকে তা দিয়ে শুরু করে। dপূর্ববর্তী উদাহরণে যদি একটি দ্বারা প্রতিস্থাপন করা হয় D, উদাহরণস্বরূপ, এক এবং দুটি উভয় ছাঁটাই করা sedহবে ।P

এই কমান্ডটি কেবল সেই লাইনের জন্য পুনরাবৃত্তি করে যা দাবী বিবৃতিতে মেলে নাs/// । যেহেতু উবস্টিটিউশন যুক্ত s///ইওলাইনটিকে সরিয়ে দেয় , এগারোর প্যাটার্ন-স্পেসের পরে আর কিছুই থাকে না ।\nNsed D

পরীক্ষাগুলি Pএবং / বা Dবাছাইভাবে প্রয়োগ করার জন্য করা যেতে পারে তবে অন্যান্য কমান্ডও রয়েছে যা সেই কৌশলটির সাথে আরও উপযুক্ত। কারণ পুনরাবৃত্তিটি ধারাবাহিক রেখাগুলি পরিচালনা করতে প্রয়োগ করা হয় যা প্রতিস্থাপনের নিয়মের কেবলমাত্র অংশের সাথে মেলে , জরায়ুর উভয় প্রান্তের সাথে মিলিত রেখার ধারাবাহিক ধারাগুলি s///ভাল কাজ করে না .:

এই ইনপুট দেওয়া:

first "line"
<second>"line"
<second>"line"
<second>line and so on

... এটি মুদ্রণ ...

first other characters "line"
<second>other characters line and so on

এটি অবশ্য পরিচালনা করে

first "line"
second "line"
<second>line

...শুধুই সুন্দর.

দ্বিতীয় আদেশ

এই কমান্ডটি তৃতীয়টির মতোই অনুরূপ। দু'জনই একটি ক্ষেত্র:b / tইস্ট লেবেল নিয়োগ করে (যেমন জোসেফ আর-এর উত্তরগুলিতেও এখানে প্রদর্শিত হয়েছে ) এবং কিছু শর্তের ভিত্তিতে এটি পুনরুক্ত করে

  • -e :n -e- পোর্টেবল sedস্ক্রিপ্টগুলি ই- লাইন বা একটি নতুন ইনলাইন জেকিউশন স্টেটমেন্টের :সাহায্যে লেবেল সংজ্ঞাটি সীমিত করে দেবে। \n-e
    • :n- নামের একটি লেবেল সংজ্ঞায়িত করে n। এটি হয় bnবা যে কোনও সময়ে যে কোনও সময়ে ফিরে যেতে পারে tn
  • tn- tএস্ট কমান্ড একটি নির্দিষ্ট লেবেলে প্রত্যাবর্তন করে (বা যদি কোনও সরবরাহ না করা হয় তবে বর্তমান লাইন-চক্রের জন্য স্ক্রিপ্টটি ছেড়ে দেয়) যদি কোনও s///লেবেল সংজ্ঞায়িত হওয়ার পরে বা এটি সর্বশেষে tএএসটিস সফল বলে অভিহিত করা হয়।

এই কমান্ডটিতে ম্যাচিং লাইনের জন্য পুনরাবৃত্তি ঘটে। যদি sedসফলভাবে সঙ্গে প্যাটার্ন প্রতিস্থাপন অন্যান্য অক্ষরের , sedরিটার্ন :nলেবেল এবং চেষ্টা আবার। যদি কোনও s///অবস্হানটি sedস্বতঃপ্রিন্ট-প্যাটার্ন-স্পেস সম্পাদন না করে এবং পরবর্তী লাইন-চক্র শুরু করে।

এটি ধারাবাহিক ক্রমগুলি আরও ভাল পরিচালনা করে। যেখানে সর্বশেষটি ব্যর্থ হয়েছিল, সেখানে এটি মুদ্রণ করে:

first other characters other characters other characters line and so on

তৃতীয় আদেশ

যেমনটি উল্লেখ করা হয়েছে, এখানে যুক্তি শেষের সাথে খুব মিল, তবে পরীক্ষাটি আরও স্পষ্ট।

  • /"$/bn- এটি sedপরীক্ষা। কারণ র‌্যাঙ্ক bকমান্ড এই ঠিকানার ফাংশন, sedকেবল একটি ইলাইন সংযুক্ত হওয়ার পরে প্যাটার্নে bফিরে আসবে এবং প্যাটার্ন-স্পেসটি ডাবল-কোট দিয়ে এখনও শেষ হবে।:n\n"

যতটা সম্ভব সম্ভব Nএবং এর মধ্যে সামান্য কাজ করা হয়েছে b- sedনীচের লাইনটি আপনার নিয়মের সাথে মেলে না তা নিশ্চিত করার জন্য এই পদ্ধতিতে খুব দ্রুত ঠিক যতটা ইনপুট প্রয়োজন তা সংগ্রহ করতে পারে gather s///Ubstitution মধ্যে এটি নিয়োগ এখানে পৃথক gএবং তাই এটি একবারে সব প্রয়োজনীয় প্রতিস্থাপন করতে হবে - lobal পতাকা। অভিন্ন ইনপুট দেওয়া এই কমান্ডটি শেষের মতো একইভাবে আউটপুট দেয়।


তুচ্ছ প্রশ্নের জন্য দুঃখিত, তবে এর অর্থ কী DATAএবং আপনি কীভাবে পাঠ্য ইনপুটটি গ্রহণ করবেন?
বোপার্ক

@ বো-পার্ক - এই উদাহরণটিতে <<\DATA\ntext input\nDATA\nবেকড রয়েছে তবে এটি কেবল এখানেsed একটি নথিতে শেল হাতে দেওয়া পাঠ্য । এটি পাশাপাশি কাজ করবে sed 'script' filenameবা process that writes to stdout | sed 'script'। এটা কি সাহায্য করে?
মাইকজার্ভ

হ্যাঁ এটা করে, ধন্যবাদ! কেন Dপ্রতিটি পরিবর্তিত লাইন ডাবল হয়? (আপনি এটি প্রয়োজনীয় হিসাবে এটি ব্যবহার করেছেন; সম্ভবত আমি sedখুব ভাল জানি না)
বোপার্ক

1
@ বাউপার্ক - বাদ দিলে আপনি দ্বিগুণ হয়ে যান Dকারণ Dঅন্যথায় Dআউটপুট থেকে আপনি এখন যা দ্বিগুণ দেখছেন তা হ'ল। আমি সবেমাত্র একটি সম্পাদনা করেছি - এবং আমি খুব শীঘ্রই এটিকে প্রসারিত করতে পারি।
মাইক্রজারভ

1
@ বোপার্ক - ঠিক আছে, আমি এটি আপডেট করেছি এবং বিকল্পগুলি সরবরাহ করেছি। এটি এখন পড়তে / বুঝতে কিছুটা সহজ হতে পারে। আমি Dবিষয়টি স্পষ্টভাবে সম্বোধনও করেছি ।
মাইক্রজারভ

7

ভাল, আমি বেশ কয়েকটি সহজ উপায় সম্পর্কে ভাবতে পারি তবে এর মধ্যে কোনওটিই জড়িত না grep(যা কোনওভাবেই বিকল্পগুলি করে না) বা sed

  1. পার্ল

    প্রতিস্থাপন করতে প্রতিটি সংঘটন "line"\n<second>সঙ্গে other charactersব্যবহার করুন:

    $ perl -00pe 's/"line"\n<second>/other characters /g' file
    first other characters line and so on
    

    বা, "line"\n<second>এক হিসাবে একাধিক, একটানা ঘটনাগুলি চিকিত্সা করতে এবং সেগুলিকে একক দিয়ে প্রতিস্থাপন other charactersকরতে, ব্যবহার করুন:

    perl -00pe 's/(?:"line"\n<second>)+/other characters /g' file
    

    উদাহরণ:

    $ cat file
    first "line"
    <second>"line"
    <second>"line"
    <second>line and so on
    $ perl -00pe 's/(?:"line"\n<second>)+/other characters /g' file
    first other characters line and so on
    

    -00"অনুচ্ছেদ মোড" যার মানে "লাইন" দ্বারা সংজ্ঞায়িত করা হয় ফাইলটি পড়ার পার্ল ঘটায় \n\nপরিবর্তে \nমূলত, প্রতিটি অনুচ্ছেদ একটি লাইন হিসাবে গণ্য হবে। প্রতিস্থাপনটি তাই একটি নতুন লাইনে জুড়ে।

  2. awk

    $  awk -v RS="\n\n" -v ORS="" '{
          sub(/"line"\n<second>/,"other characters ", $0)
          print;
        }' file 
    first other characters line and so on
    

    একই বেসিক ধারণাটি, আমরা পুরো ফাইলটি স্লাপ করতে রেকর্ড বিভাজক ( RS) সেট করেছিলাম \n\n, তারপরে আউটপুট রেকর্ড বিভাজককে কিছুই নয় (অন্যথায় একটি অতিরিক্ত নিউলাইন প্রিন্ট করা হয়) এবং তারপরে sub()প্রতিস্থাপনটি করতে ফাংশনটি ব্যবহার করি ।


2
@mikeserv? কোনটি? দ্বিতীয়টির ধারণা করা হয়, ওপি বলেছিল যে তারা "এক বা একাধিক ঘটনাকে প্রতিস্থাপন করতে চায়", তাই অনুচ্ছেদটি খাওয়া তাদের প্রত্যাশা মতো হতে পারে।
টেরডন

খুব ভাল পয়েন্ট। আমি অনুমান করি যে আমি প্রতিবার আরও বেশি মনোযোগ দিয়েছি এবং অর্জন করেছি, তবে আমার ধারণা এটি স্পষ্ট নয় যে ঘটনাটি প্রতি এক প্রতিস্থাপন বা ঘটনার ক্রম প্রতি এক প্রতিস্থাপন হওয়া উচিত ... @ বউপার্ক?
মাইক্রোসার্ভ

এটি প্রতিটি ঘটনার জন্য প্রতিস্থাপনের প্রয়োজন।
বোপার্ক

@ বাউপার্ক ঠিক আছে, তারপরে প্রথম পার্ল অ্যাপ্রোচ বা অ্যাজক উভয়ই কাজ করা উচিত। তারা আপনাকে পছন্দসই আউটপুট দেয় না?
টেরডন

এটি কাজ করে, আপনাকে ধন্যবাদ, তবে তৃতীয় লাইনটি awkহওয়া উচিত print;}' file। আমাকে পার্ল এড়াতে এবং অগ্রাধিকার হিসাবে ব্যবহার করতে হবে sed, যাইহোক আপনি ভাল বিকল্পগুলির পরামর্শ দিয়েছেন।
বোপার্ক

6

পুরো ফাইলটি পড়ুন এবং একটি বিশ্বব্যাপী প্রতিস্থাপন করুন:

sed -n 'H; ${x; s/"line"\n<second>/other characters /g; p}' <<END
first "line"
<second> line followed by "line"
<second> and last
END
first other characters  line followed by other characters  and last

হ্যাঁ. এটি কাজ করে, তবে আমার যদি একাধিক ঘটনা ঘটে?
বোপার্ক

হু, ঠিক আছে। স্থির
গ্লেন জ্যাকম্যান

1
আবার নিটপিকের জন্য দুঃখিত, তবে ${cmds}এটি জিএনইউ-নির্দিষ্ট - বেশিরভাগ অন্যান্যর sedজন্য একটি \newline বা এবং এর -eমধ্যে একটি বিরতি প্রয়োজন । আপনি বন্ধনী পুরাপুরি এড়াতে পারেন - এবং portably - এবং এমনকি একটি অতিরিক্ত ঢোকাতে এড়াতে মত প্রথম লাইনে ewline অক্ষর:p}\nsed 'H;1h;$!d;x;s/"line"\n<second>/other characters /g'
mikeserv

আমি এটি পরীক্ষা করেছি এবং এটি বহনযোগ্য নয় বলে মনে হচ্ছে। এটি আউটপুটের শুরুতে একটি অতিরিক্ত নতুন লাইন মুদ্রণ করে তবে ফলাফলটি জিএনইউতে সঠিক।
বোপার্ক

শীর্ষস্থানীয় নিউলাইনটি সরানোর জন্য: sed -n '1{h;n};H; ${x; s/"line"\n<second>/other characters /g; p}'- তবে এটি অনাদায়ী।
গ্লেন জ্যাকম্যান

3

এখানে গ্লেনের উত্তরের একটি বৈকল্পিকতা রয়েছে যা যদি আপনার একাধিক ঘটনা ঘটে থাকে (তবে sedকেবলমাত্র জিএনইউতে কাজ করে ) কাজ করবে:

sed ':x /"line"/N;s/"line"\n<second>/other characters/;/"line"/bx' your_file

:xশাখাবিন্যাস জন্য শুধু একটি লেবেল লেগে রয়েছে। মূলত, এটি কী করে তা হ'ল এটি প্রতিস্থাপনের পরে লাইনটি পরীক্ষা করে এবং যদি এটি এখনও মেলে তবে এটি লেবেলে "line"ফিরে শাখা করে :x( এটিই কি bxকরে) এবং বাফারে আরও একটি লাইন যুক্ত করে এটি প্রক্রিয়াজাতকরণ শুরু করে।


@ মিকসার্ভ দয়া করে আপনার অর্থ সম্পর্কে সুনির্দিষ্ট হন। এটা আমার জন্য কাজ করেছে।
জোসেফ আর।

@ মিকসার্ভ আমি দুঃখিত, আপনি কী বলছেন তা আমি সত্যিই জানি না। আমি আমার টার্মিনালে উপরের কোড লাইনটি অনুলিপি করেছি এবং এটি সঠিকভাবে কাজ করেছে।
জোসেফ আর

1
প্রত্যাহার করা - এটি জিএনইউতে দৃশ্যত কাজ করে sed যা তার নন-পসিক্স লেবেলটিকে লেবেল ঘোষণার জন্য ডিলিমিটার হিসাবে স্থান গ্রহণ করার জন্য যথেষ্ট পরিমাণে হ্যান্ডলিং গ্রহণ করে। আপনার অবশ্যই লক্ষ্য করা উচিত, অন্য যে কোনও sedজায়গায় ব্যর্থ হবে - এবং এর জন্য ব্যর্থ হবে N। জিএনইউ শেষ লাইনে sedপ্রস্থান ছাড়ার আগে প্যাটার্স-স্পেস মুদ্রণের জন্য পসিক্স নির্দেশিকা ভঙ্গ করে N, তবে পসিক্স এটি পরিষ্কার করে দিয়েছে যে Nশেষ লাইনে কোনও কমান্ড পড়লে কিছুই প্রিন্ট করা উচিত নয়
মাইকজার্ভ

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

1
যে ক্ষেত্রে আমি অফার করবে আরও একটি - এই portably মত করা সম্ভব: sed -e :x -e '/"line"/{$!N' -e '};s/"line"\n<second>/other characters/;/"line"/bx'
মাইক্রোসার্ভ
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.