শেড দিয়ে শুধুমাত্র প্রথম ঘটনাটি বিকল্প করতে চান


26

আসল ফাইল

claudio
antonio
claudio
michele

আমি "ক্লৌদিও" এর সাথে প্রথম ক্লাসিয়োইনটিকে "ক্লডিয়া" দিয়ে পরিবর্তন করতে চাই যাতে ফাইলের ফলাফল হয়

claudia
antonio
claudio
michele

আমি চেষ্টা করেছি

sed -e '1,/claudio/s/claudio/claudia/' nomi

তবে একটি বৈশ্বিক প্রতিস্থাপন সম্পাদন করুন? কেন?


এখানে দেখুন linuxtopia.org/online_books/linux_tool_guides/the_sed_faq/... এবং info sed: ( 0,/REGEXP/: 0 একটি লাইন নম্বর মত একটি ঠিকানা স্পেসিফিকেশন ব্যবহার করা যেতে পারে 0,/REGEXP/, যাতে sedপ্রথম ইনপুট লাইন খুব RegExp মেলানোর চেষ্টা করবে অন্য কথায়,। 0,/REGEXP/হয় অনুরূপ 1,/REGEXP/, যদি এডিডিআর 2 ইনপুটটির প্রথম লাইনের সাথে মেলে তবে 0, / আরইজিইএক্সপি / ফর্ম এটি পরিসীমাটি শেষ করার জন্য বিবেচনা করবে, যেখানে 1, / আরজিইএক্সপি / ফর্মটি তার পরিসীমাটির শুরুতে মিলবে এবং তাই ব্যাপ্তিটির স্প্যান তৈরি করবে আপ দ্বিতীয় রেগুলার এক্সপ্রেশন) এর সংঘটন
jimmij


awk '/claudio/ && !ok { sub(/claudio/,"claudia"); ok=1 } 1' nomiকরণীয়
অ্যাডাম কাটজ

উত্তর:


23

আপনি যদি জিএনইউ ব্যবহার করছেন তবে sedচেষ্টা করুন:

sed -e '0,/claudio/ s/claudio/claudia/' nomi

sedRegex যে পর্যন্ত একটি সীমার শেষ হয় পরীক্ষা করার শুরু হয় না পরে যে শুরু করে সীমার লাইন।

থেকে man sed(POSIX র manpage, জোর খনি):

দুটি ঠিকানা সহ একটি সম্পাদনা কমান্ড অন্তর্ভুক্ত ব্যাপ্তি নির্বাচন করবে
প্রথম প্যাটার্ন স্থান যে মাধ্যমে প্রথম ঠিকানার সাথে মেলায় থেকে
পরের প্যাটার্ন স্পেস যা দ্বিতীয়টির সাথে মেলে। 

ব্যবহার awk

awkআপনি যেমন প্রত্যাশা করেছিলেন তেমন কাজের ক্ষেত্রগুলি আরও:

$ awk 'NR==1,/claudio/{sub(/claudio/, "claudia")} 1' nomi
claudia
antonio
claudio
michele

ব্যাখ্যা:

  • NR==1,/claudio/

    এটি এমন একটি পরিসীমা যা লাইন 1 দিয়ে শুরু হয় এবং প্রথম সংঘটন দিয়ে শেষ হয় claudio

  • sub(/claudio/, "claudia")

    আমরা সীমার মধ্যে থাকা অবস্থায় এই বিকল্প কমান্ডটি কার্যকর করা হয়।

  • 1

    লাইনটি প্রিন্ট করার জন্য এই awk এর ক্রিপ্টিক শর্টহ্যান্ড।


1
এটি sedযদিও জিএনইউ ধরে নেয় ।
স্টাফেন চেজেলাস

@ স্টাফেনচাজলাস পসিক্সএলএইচআরসিটি সেট করা থাকলে এটিও কাজ করে তবে আমার ধারণা এটি আমার পছন্দমতো বেশি নয় mean উত্তর আপডেট হয়েছে (বিএসডি পরীক্ষা মেশিনের জন্য আমার অভাব আছে)।
1024

বুলিয়ান স্ট্যাটাস ভেরিয়েবলের সাহায্যে আইএমও, আইএমও সহজ হতে পারে:awk '!r && /claudio/ {sub(/claudio/,"claudia"); r=1} 1'
গ্লেন জ্যাকম্যান

@glennjackman বাawk !x{x=sub(/claudio/,"claudia")}1

আমি প্রথম অংশে কোনও আলাদা ডিলিমিটারও সফলভাবে ব্যবহার করতে পারিনি:0,/claudio/
প্যাট মাইরন

4

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

sed -n ':a;N;$bb;ba;:b;s/\(claudi\)o/\1a/;p' file
sed -n '1h;1!H;${g;s/\(claudi\)o/\1a/;p;}' file

ভাষ্য সহ:

sed -n '                # don't implicitly print input
  :a                    # label "a"
  N                     # append next line to pattern space
  $bb                   # at the last line, goto "b"
  ba                    # goto "a"
  :b                    # label "b"
  s/\(claudi\)o/\1a/    # replace
  p                     # and print
' file
sed -n '                # don't implicitly print input
  1h                    # put line 1 in the hold space
  1!H                   # for subsequent lines, append to hold space
  ${                    # on the last line
    g                     # put the hold space in pattern space
    s/\(claudi\)o/\1a/    # replace
    p                     # print
  }
' file

3

জিএনইউর একটি নতুন সংস্করণ বিকল্পটিকে sedসমর্থন করে -z

সাধারণত, সেড একটি লাইন পড়েন শেষ-অব-লাইন অক্ষর (নতুন লাইন বা ক্যারেজ ফিরতি) অবধি অক্ষরের একটি স্ট্রিং পড়ে।
এর পরিবর্তে "NULL" অক্ষরটি ব্যবহার করার জন্য সেডের GNU সংস্করণ 4.2.2 সংস্করণে একটি বৈশিষ্ট্য যুক্ত করেছে। এটি দরকারী হতে পারে যদি আপনার কাছে এমন ফাইল থাকে যা NULL রেকর্ড বিভাজক হিসাবে ব্যবহার করে। কিছু জিএনইউ ইউটিলিটি আউটপুট জেনারেট করতে পারে যা NUL এর পরিবর্তে একটি নতুন লাইন ব্যবহার করে, যেমন "Find। -Print0" বা "grep -lZ"।

আপনি যখন sedবিভিন্ন লাইনে কাজ করতে চান তখন আপনি এই বিকল্পটি ব্যবহার করতে পারেন ।

echo 'claudio
antonio
claudio
michele' | sed -z 's/claudio/claudia/'

আয়

claudia
antonio
claudio
michele

1

awkপ্রতিস্থাপনটি ইতিমধ্যে সম্পন্ন হয়েছে কিনা তা জানতে আপনি একটি পতাকা ব্যবহার করতে পারেন । যদি তা না হয় তবে এগিয়ে যান:

$ awk '!f && /claudio/ {$0="claudia"; f=1}1' file
claudia
antonio
claudio
michele

1

আপনি যদি কিছুটা বিলম্ব স্থির করেন তবে এটি আসলেই সহজ - অবিশ্বাস্য এক্সটেনশনে পৌঁছানোর দরকার নেই:

sed '$H;x;1,/claudio/s/claudio/claudia/;1d' <<\IN
claudio
antonio
claudio
michele
IN

এটি কেবল প্রথম লাইনটিকে দ্বিতীয় এবং দ্বিতীয় তৃতীয় এবং অন্যদিকে স্থগিত করে

এটি প্রিন্ট করে:

claudia
antonio
claudio
michele

1

এবং আরও একটি বিকল্প

sed --in-place=*.bak -e "1 h;1! H;\$! d;$ {g;s/claudio/claudia/;}" -- nomi

সুবিধাটি হ'ল এটি ডাবল কোটেশন ব্যবহার করে, যাতে আপনি ভিতরে ভেরিয়েবল ব্যবহার করতে পারেন।

export chngFrom=claudio
export chngTo=claudia
sed --in-place=*.bak -e "1 h;1! H;\$! d;$ {g;s/${chngFrom}/${chngTo}/;}" -- nomi

1
হ্যাঁ তুমি সঠিক. সাধারণ ধারণা একই। তবে, দয়া করে, একককে সরাসরি ডাবল উদ্ধৃতিতে স্থান দেওয়ার চেষ্টা করুন এবং দেখুন এটি কার্যকর কিনা। শয়তান বিশদে পড়ে আছে। এই উদাহরণে এগুলি স্পেস এবং একটি পলায়ন। আমি বিশ্বাস করি যে পূর্ববর্তী উত্তরগুলির এই ধারাবাহিকতা কারও সময় সাশ্রয় করতে পারে। এবং এই কারণেই আমি পোস্টটি প্রকাশের সিদ্ধান্ত নিয়েছি।
utom

1

এটি হোল্ড স্পেস ছাড়াই এবং প্যাটার্ন স্পেসে সমস্ত লাইনকে ছাড়াই করা যায়:

sed -n '/claudio/{s/o/a/;bx};p;b;:x;p;n;bx' nomi

ব্যাখ্যা: আমরা "ক্লডিও" খুঁজে পেতে চেষ্টা এবং আমরা ছোট মধ্যে প্রিন্ট লোড লুপ মধ্যে তিড়িং লাফ যদি আমরা এটা করতে :xএবং bx। অন্যথায় আমরা পরবর্তী লাইনটি দিয়ে স্ক্রিপ্টটি মুদ্রণ এবং পুনঃসূচনা করি।

sed -n '      # do not print lines by default
  /claudio/ { # on lines that match "claudio" do ...
    s/o/a/    # replace "o" with "a"
    bx        # goto label x
  }           # end of do block
  p           # print the pattern space
  b           # go to the end of the script, continue with next line
  :x          # the label x for goto commands
  p           # print the pattern space
  n           # load the next line in the pattern space (clearing old contents)
  bx          # goto the label x
  ' nomi

1
sed -n '/claudia/{p;Q}'

sed -n '           # don't print input
    /claudia/      # regex search
    {              # when match is found do
    p;             # print line
    Q              # quit sed, don't print last buffered line
    {              # end do block

1
প্রশ্ন পড়ে বিরক্ত করেছেন?
don_crissti

1

sumary

জিএনইউ সিনট্যাক্স:

sed '/claudio/{s//claudia/;:p;n;bp}' file

বা এমনকি (শব্দটি প্রতিস্থাপনের জন্য কেবল একবার ব্যবহার করতে:

sed '/\(claudi\)o/{s//\1a/;:p;n;bp}' file

বা, পসিক্স সিনট্যাক্সে:

sed -e '/claudio/{s//claudia/;:p' -e 'n;bp' -e '}' file

যে কোন সিড, প্রক্রিয়া উপর কাজ করে শুধুমাত্র অনেক লাইন হিসাবে প্রথম এটি করা প্রয়োজন যেমন claudio, কাজ করে এমনকি যদি claudioপ্রথম লাইন রয়েছে এবং যেমন শুধুমাত্র একটি Regex স্ট্রিং ব্যবহার খাটো।

বিস্তারিত

শুধুমাত্র একটি লাইন পরিবর্তন করতে আপনার কেবল একটি লাইন নির্বাচন করতে হবে ।

ব্যবহার করে একটি 1,/claudio/ (আপনার প্রশ্ন থেকে) নির্বাচন করে:

  • প্রথম লাইন থেকে (নিঃশর্ত)
  • থেকে পরবর্তী লাইন স্ট্রিং ধারণ করে claudio
$ cat file
claudio 1
antonio 2
claudio 3
michele 4

$ sed -n '1,/claudio/{p}' file
claudio 1
antonio 2
claudio 3

যে কোনও লাইন রয়েছে তা নির্বাচন করতে claudio, ব্যবহার করুন:

$ sed -n `/claudio/{p}` file
claudio 1
claudio 3

এবং ফাইলটিতে কেবল প্রথমটি নির্বাচন করতে claudio, ব্যবহার করুন:

sed -n '/claudio/{p;q}' file
claudio 1

তারপরে, আপনি কেবলমাত্র সেই লাইনে একটি প্রতিস্থাপন করতে পারেন:

sed '/claudio/{s/claudio/claudia/;q}' file
claudia 1

যা লাইনে কেবলমাত্র রেগেক্স ম্যাচের প্রথম ঘটনাটি বদলে দেবে , এমনকি সেখানে একের বেশি থাকতে পারে প্রথম লাইনে যা রেজেক্সের সাথে মেলে।

অবশ্যই, /claudio/রেজেক্স এটিকে সরল করা যেতে পারে:

$ sed '/claudio/{s//claudia/;q}' file
claudia 1

এবং, তখন, কেবলমাত্র অনুপস্থিত যা হ'ল অন্য সমস্ত লাইন অপরিশোধিত মুদ্রণ করা:

sed '/claudio/{s//claudia/;:p;n;bp}' file
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.