অনুক্রমিক সূচক সহ স্ট্রিং প্রতিস্থাপন করুন


10

কেউ এটি সম্পাদন করার জন্য একটি মার্জিত উপায় প্রস্তাব করতে পারেন?

ইনপুট:

test  instant  ()

test  instant  ()

...
test  instant  ()    //total 1000 lines

আউটপুট হওয়া উচিত:

test      instant1  ()

test      instant2  ()

test      instant1000()

খালি লাইনগুলি আমার ইনপুট ফাইলগুলিতে রয়েছে এবং একই ডিরেক্টরিতে অনেকগুলি ফাইল রয়েছে যা আমাকে একবারে প্রক্রিয়া করা প্রয়োজন।

আমি অনেক চেষ্টা করেছিলাম একই ডিয়ারে অনেকগুলি ফাইল প্রতিস্থাপন করতে এবং কাজ করে নি।

for file in ./*; do perl -i -000pe 's/instance$& . ++$n/ge' "$file"; done

ত্রুটি:

Substitution replacement not terminated at -e line 1.
Substitution replacement not terminated at -e line 1.

এবং আমি এটি চেষ্টা করেছিলাম:

perl -i -pe 's/instant/$& . ++$n/ge' *.vs

এটি কাজ করেছে তবে সূচকটি কেবল এক থেকে অন্য ফাইলে বর্ধন করে চলেছে। নতুন ফাইলে পরিবর্তনের পরে আমি এটিকে 1 এ পুনরায় সেট করতে চাই। কোন ভাল পরামর্শ?

find . -type f -exec perl -pi -e 's/instant/$& . ++$n{$ARGV}/ge' {} +

কাজ করে তবে এটি অন্য সমস্ত ফাইল প্রতিস্থাপন করা উচিত নয়। আমি *.txtকেবলমাত্র ফাইলগুলি প্রতিস্থাপন করতে পছন্দ করি ।


এবং এগুলি কি কেবল ফাঁকা রেখাগুলির সমন্বয়েই বা গঠিত test instant ()?
terdon

আমি দ্বিগুণ ব্যবধানযুক্ত রেখাগুলি আবার ফিরিয়ে দিয়েছি, তারা প্রায়শই নতুন ব্যবহারকারীদের জন্য এই সাইটের মার্কআপ কীভাবে ব্যবহার করতে হয় তা না জানার লক্ষণ, এ কারণেই আপনার ফাইলের সামগ্রী ব্লককে সঠিকভাবে ইনডেন্ট করার সময় টেরডন এগুলি সরিয়ে ফেললেন যাতে এটি ফাইলের সামগ্রী হিসাবে প্রদর্শিত হয়। আশা করি এখন ঠিক আছে।
টিমো

উত্তর:


14
perl -pe 's/instant/$& . ++$n/ge'

বা জিএনইউ সহ awk:

awk -vRS=instant '{$0=n$0;ORS=RT}++n'

জায়গায় জায়গায় ফাইলগুলি সম্পাদনা করতে, -iবিকল্পটি এতে যুক্ত করুন perl:

perl -pi -e 's/instant/$& . ++$n{$ARGV}/ge' ./*.vs

বা পুনরাবৃত্তির সাথে:

find . -name '*.vs' -type f -exec perl -pi -e '
  s/instant/$& . ++$n{$ARGV}/ge' {} +

ব্যাখ্যা

perl -pe 's/instant/$& . ++$n/ge'

-pলাইন দ্বারা ইনপুট লাইনটি প্রক্রিয়া করা, -eপ্রতিটি লাইনের জন্য প্রদত্ত অভিব্যক্তিটি মূল্যায়ন করুন এবং এটি মুদ্রণ করুন। প্রতিটি লাইনে জন্য, আমরা (ব্যবহার প্রতিস্থাপন s/re/repl/flagsঅপারেটর) instantনিজেই (জন্য $&) এবং একটি ভেরিয়েবলের বৃদ্ধি মান ++$ngপতাকা বিশ্বব্যাপী (শুধু একবার নয়) প্রতিকল্পন করা হয়, এবং eযাতে প্রতিস্থাপন Perl কোড হিসেবে ব্যাখ্যা করা হয় valuate (একটি নির্দিষ্ট স্ট্রিং)।

ইন-প্লেস সম্পাদনার জন্য যেখানে একটি পার্ল অনুরোধ একাধিক ফাইলের প্রক্রিয়া করে, আমরা $nপ্রতিটি ফাইলটিতে পুনরায় সেট করতে চাই । পরিবর্তে, আমরা ব্যবহার করি $n{$ARGV}( $ARGVবর্তমানে প্রক্রিয়াজাত ফাইলটি কোথায় )।

awkএক ব্যাখ্যা একটি বিট দাবী করে।

awk -vRS=instant '{$0=n$0;ORS=RT}++n'

আমরা awkস্বেচ্ছাসেবী স্ট্রিংগুলিতে রেকর্ড পৃথক করতে এমনকি জিএনইউর সক্ষমতা ব্যবহার করছি (এমনকি রিজেক্সপস)। সঙ্গে -vRS=instant, আমরা সেট রেকর্ড বিভাজক থেকে instantRTপরিবর্তনশীল হ'ল যা যা মিলেছে RSতাই ধরে রাখে , তাই instantশেষ রেকর্ড ব্যতীত যেখানে এটি খালি স্ট্রিং হবে। রেকর্ডগুলির উপরে ইনপুটটিতে ( $0) এবং রেকর্ড টার্মিনেটর ( RT) হ'ল ( [$0|RT]):

[test  |instant][  ()
test  |instant][  ()
...
test  |instant][  ()    //total 1000 lines|]

সুতরাং আমাদের যা করতে হবে তা হ'ল প্রথমটি বাদে প্রতিটি রেকর্ডের শুরুতে একটি বর্ধনকারী সংখ্যা numberোকানো।

আমরা উপরে কি কি। প্রথম রেকর্ডের জন্য, nখালি থাকবে। আমরা আরটি সেট করেছিলাম (̲utut r̲ecord s̲eparator ) আরটি তে, যাতে awk প্রিন্ট হয় n $0 RT। এটি দ্বিতীয় প্রকাশের ( ++n) এর উপরে এটি করে যা একটি শর্ত যা সর্বদা সত্যের (একটি শূন্য নম্বরের) মূল্যায়ন করে এবং তাই $0 ORSপ্রতিটি রেকর্ডের জন্য ডিফল্ট ক্রিয়া (মুদ্রণের ) সম্পাদিত হয়।



5

sedকাজের জন্য সত্যিই সেরা সরঞ্জাম নয়, আপনি আরও ভাল স্ক্রিপ্টিং ক্ষমতা সহ কিছু চান। এখানে কিছু পছন্দ রয়েছে:

  • Perl

    perl -00pe 's/instant/$& . $./e' file 

    যার -pঅর্থ যা স্ক্রিপ্ট দেওয়া আছে তা প্রয়োগ করার পরে "প্রতিটি লাইন মুদ্রণ করুন" -e-00"অনুচ্ছেদ মোড" তাই রেকর্ড (লাইন) সক্রিয় পরপর সম্পর্কে newline দ্বারা সংজ্ঞায়িত করা হয় ( \n) অক্ষর, এই এটি সঠিকভাবে ডবল ব্যবধানযুক্ত লাইন সাথে মোকাবিলা করতে দেয়। $&শেষ প্যাটার্নটি মিলছে এবং $.এটি ইনপুট ফাইলের বর্তমান লাইন নম্বর। eমধ্যে s///eআমাকে প্রতিকল্পন অপারেটর এক্সপ্রেশন মূল্যায়ন করতে পারবেন।

  • awk (এটি ধরে নিয়েছে যে আপনার ডেটা ঠিক তিনটি স্থান পৃথকীকরণ ক্ষেত্রের সাথে দেখানো হয়েছে)

    awk '{if(/./) print $1,$2 ++k,$3; else print}' file 

    এখানে, আমরা বাড়ায় kপরিবর্তনশীল kশুধুমাত্র যদি বর্তমান লাইন খালি না থাকে /./যে ক্ষেত্রে আমরা প্রয়োজনীয় তথ্য প্রিন্ট করা হবে। খালি লাইনগুলি যেমন প্রিন্ট করা হয়।

  • বিভিন্ন শেল

     n=0; while read -r a b c; do 
       if [ "$a" ] ; then 
          (( n++ ))
          printf "%s %s%s %s\n" "$a" "$b" "$n" "$c"
       else
          printf "%s %s %s\n" "$a" "$b" "$c"
       fi
     done < file 
    

    এখানে, প্রতিটি ইনপুট লাইন স্বয়ংক্রিয়ভাবে সাদা স্পেসে বিভক্ত হয় এবং ক্ষেত্রগুলি $a, $bএবং হিসাবে সংরক্ষণ করা হয় $c। তারপরে, লুপের মধ্যে, $cপ্রতিটি লাইনের জন্য একটি দ্বারা বাড়ানো হয় যার $aজন্য খালি নয় এবং এটির বর্তমান মানটি দ্বিতীয় ক্ষেত্রের পাশে মুদ্রিত হয় $b,।

দ্রষ্টব্য: উপরের সমস্ত সমাধানগুলি ধরে নিচ্ছে যে ফাইলের সমস্ত লাইন একই ফর্ম্যাট। যদি তা না হয় তবে @ স্টিফেনের উত্তর হ'ল উপায়।


অনেকগুলি ফাইলের সাথে ডিল করার জন্য এবং ধরে নেওয়া যে আপনি বর্তমান ডিরেক্টরিতে সমস্ত ফাইলের সাথে এটি করতে চান , আপনি এটি ব্যবহার করতে পারেন:

for file in ./*; do perl -i -00pe 's/instant/$& . $./e' "$file"; done

যত্নবান: এটি কোনও ফাঁকা জায়গা ছাড়া সহজ ফাইলের নাম ধরে নিয়েছে, যদি আরও জটিল কিছু মোকাবেলা করার প্রয়োজন হয়, তবে (ধরে নিবেন ksh93, zshবা bash) যান:

find . -type f -print0 | while IFS= read -r -d ''; do
    perl -i -00pe 's/instant/$& . $./e' "$file"
done

পার্ল স্ক্রিপ্ট কাজ করে। লাইনগুলি দ্বিগুণ স্থান হলে তবে একটি ছোট সমস্যা আছে।
ব্যবহারকারী3342338

@ ব্যবহারকারী ৩৩৩৩৩৩৩৩ হ্যাঁ, যেহেতু আমি বর্তমান লাইন নম্বরটি ব্যবহার করছি সেহেতু এটি কাউন্টারটিকে বাড়িয়ে তুলবে। এটি একটি খুব নির্বোধ পন্থা, যেমনটি আমি বলেছিলাম স্টিফেন আরও দৃust়। আপনার ফাঁকা লাইন থাকলে বা আপনার লাইনগুলির কোনও যদি আপনি যা দেখায় তা থেকে বিচ্যুত হয় তবে এগুলির কোনওটিই কাজ করে না।
terdon

@ ব্যবহারকারী3342338 আপডেট হওয়া উত্তর দেখুন। তাদের এখনই ডাবল স্পেসযুক্ত ফাইলগুলির জন্য কাজ করা উচিত।
terdon

দুর্দান্ত উত্তর এবং বিকল্প পদ্ধতির বিকল্প !! ধন্যবাদ
মাদ্রিবাদ

0

আপনি যদি এর সাথে সমাধান sedকরতে চান তবে এই জাতীয় ব্যবহার করতে পারেন (ইন bash):

i=0
while read -r line; do
  sed "s/\(instant\)/\1${i}/" <<< "${line}"
  [[ ${line} =~ instant ]] && i=$(( i + 1 ))
done < file

বা আরও বহনযোগ্য সমাধান হ'ল:

i=0
while read -r line; do
  echo "${line}" | sed "s/\(instant\)/\1${i}/"
  if echo "${line}" | grep -q inst; then
    i=$(( i + 1 ))
  fi
done < file
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.