একটি বড় ফোল্ডার শ্রেণিবিন্যাসে পাঠ্য প্রতিস্থাপন কীভাবে করবেন?


11

আমি কয়েকটি উদাহরণ ব্যতীত বড় আকারের ফাইলগুলিতে কিছু পাঠ্য অনুসন্ধান করতে এবং প্রতিস্থাপন করতে চাই। প্রতিটি লাইনের জন্য, আমি আমাকে জিজ্ঞাসা করে একটি প্রম্পট চাই যে আমাকে line লাইনটি প্রতিস্থাপন করতে হবে কিনা। ভিমের অনুরূপ কিছু :%s/from/to/gc( cনিশ্চিতকরণের অনুরোধের সাথে), তবে ফোল্ডারগুলির একটি সেট জুড়ে। কিছু ভাল কমান্ড লাইন সরঞ্জাম বা স্ক্রিপ্ট ব্যবহার করা যেতে পারে?


যথাযথ ফর্ম্যাটিংয়ের গুরুত্ব সম্পর্কে: আমি প্রথমে আপনার কমান্ডটি s/from/to/gপরে ফরম্যাটিং গ্লুইচের মতো পড়তে চাইতাম , বরং আপনি যেভাবে লেখার চেষ্টা করেছিলেন তার s/from/to/gcউপর জোর দেওয়ার চেয়ে c(আপনি মার্কডাউন দিয়ে এটি করতে পারবেন না, আপনি এটি দিয়ে করতে পারতেন) <code>এবং <strong>এইচটিএমএল ট্যাগ)।
গিলস 'অসন্তুষ্ট হওয়া বন্ধ করুন'

উত্তর:


19

ভিম ব্যবহার করবেন না কেন?

সমস্ত ফাইল vim খুলুন

vim $(find . -type f)

বা কেবল প্রাসঙ্গিক ফাইলগুলি খুলুন (কালেব প্রস্তাবিত)

vim $(grep 'from' . -Rl)

এবং তারপরে সমস্ত বাফারগুলিতে প্রতিস্থাপন চালান

:bufdo %s/from/to/gc | update

আপনি এটি দিয়েও করতে পারেন sed, তবে আমার জ্ঞান সীমিত।


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

1
আপনি বর্তমান বাফারে সমস্ত ফাইল না খোলার grepপরিবর্তে এটি ব্যবহার findকরতে পারেন যাতে আপনি কেবল সেই ফাইলগুলি খোলেন যা ম্যাচগুলি জানে। vim $(grep 'from' . -Rl)
কালেব

ধন্যবাদ। (অ্যাস্ট্রিটিকস সি এর চারপাশে) দরকার? বা এটি একটি বিন্যাস সমস্যা?
বালকি

@ বালকি এটি একটি "ফর্ম্যাটিং" সমস্যা। এটি স্থির করে
গার্ট

5

আপনি একটি ছোট পার্ল স্ক্রিপ্ট সহ কিছু অপরিশোধিত কাজ করতে পারেন যা -l -peআর্গুমেন্ট ( -i) হিসাবে পাস করা ফাইলগুলিতে স্থানে লাইন ( ) দ্বারা প্রতিস্থাপন লাইন সম্পাদন করার নির্দেশ দেওয়া হয়েছে :

perl -i -l -pe '
    if (/from/) {                            # is the source text present on this line?
        printf STDERR ("%s: %s [y/N]? ", $ARGV, $_);  # display a prompt
        $r=<STDIN>;                                   # read user response
        if ($r =~ /^[Yy]/) {                          # if user entered Y:
            s/from/to/g;                              # replace all occurences on this line
    }' /path/to/files

সম্ভাব্য উন্নতিগুলি হ'ল প্রম্পটের অংশগুলি রঙ করা এবং "বর্তমান ফাইলের সমস্ত উপস্থিতি প্রতিস্থাপন করুন" এর মতো জিনিসগুলিকে সমর্থন করা। একটি লাইনে প্রতিটি ঘটনার জন্য পৃথকভাবে অনুরোধ করা আরও শক্ত হবে।

দ্বিতীয় অংশ, ফাইলগুলি মিলছে। যদি খুব বেশি সংখ্যক ফাইল জড়িত না থাকে এবং আপনি zsh চালাচ্ছেন তবে আপনি বর্তমান ডিরেক্টরি এবং এর উপ-ডিরেক্টরিগুলির সমস্ত ফাইলকে পুনরাবৃত্তভাবে মিলিয়ে নিতে পারেন:

perl -i -l -pe '…' **/*(.)

যদি আপনার শেলটি ব্যাশ ≥4 হয় perl … **/*তবে আপনি চালনা করতে পারেন তবে এটি উদ্দীপনাজনিত ত্রুটি বার্তা তৈরি করবে কারণ সেড ডিরেক্টরিতে চালানোর চেষ্টা করবে (এবং ব্যর্থ)। আপনি যদি কেবল সি ফাইলের মতো ফাইলে সেট করে প্রতিস্থাপন করতে চান তবে আপনি ম্যাচগুলি সীমাবদ্ধ করতে পারেন (যা বাশ ≥4 বা zsh এর মধ্যে কাজ করে):

perl -i -l -pe '…' **/*.[hc]

আপনি যে ফাইলগুলি প্রতিস্থাপন করছেন তার উপর যদি আপনার আরও নিয়ন্ত্রণের প্রয়োজন হয় বা আপনার শেলটিতে পুনরাবৃত্ত ডিরেক্টরিটি মিলছে না বা আপনার **যদি খুব বেশি ফাইল রয়েছে এবং একটি "কমান্ড লাইন খুব দীর্ঘ" ত্রুটি পেয়ে থাকেন তবে ব্যবহার করুন find। উদাহরণস্বরূপ, নামযুক্ত সমস্ত ফাইল *.hবা *.cবর্তমান ডিরেক্টরি এবং এর উপ-ডিরেক্টরিগুলিতে প্রতিস্থাপন সম্পাদন করতে (পুরানো সিস্টেমে, আপনাকে লাইনের শেষের \;পরিবর্তে ব্যবহার করতে হবে +( +ফর্মটি দ্রুত তবে সর্বত্র উপলব্ধ নয়)।

find . -type f -name '*.[hc]' -exec perl -i -l -pe '…' {} +

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

ইম্যাক্সে, আপনি এখানে এটি কীভাবে করতে পারেন তা এখানে:

  1. M-x find-name-dired(শীর্ষস্থানীয় ডিরেক্টরি M-x find-diredনির্দিষ্ট করুন ) বা (একটি স্বেচ্ছাসেবক findকমান্ড লাইন নির্দিষ্ট করুন ) দিয়ে ফাইলের নাম সংগ্রহ করুন ।
  2. ফলে সালে dired বাফার, প্রেস tসমস্ত ফাইল, চিহ্নিত করতে তারপর Q( dired-do-query-replace-regexp) হিসাবে চিহ্নিত ফাইল প্ররোচনা সঙ্গে একটি প্রতিস্থাপন সঞ্চালন।

1

sdiff(দেখুন http://www.gnu.org/software/diffutils/manual/diffutils.html#Invoking-sdiff ) এখানে কার্যকর হতে পারে। এটির সাহায্যে আপনি ইন্টারেক্টিভ প্যাচিং করতে পারেন। সুতরাং এটি ব্যবহার করে প্রতিস্থাপন অপারেশন করে আপনি তৈরি একটি অস্থায়ী ফাইলের সাথে এটি sedকরা একটি সম্ভাব্য সমাধান হতে পারে:

# use file descriptor 3 to still allow use of stdin
while IFS= read -r -d '' file <&3; do

  # write the result of the replacement into a temporary file
  sed -r 's/something/something_else/g' -- "$file" > replacer_tmp

  if cmp -s -- "$file" replacer_tmp; then
    continue; # nothing was replaced
  fi

  echo "There is something to replace in '$file'! Starting interactive diff."
  echo

  sdiff -o "$file" -s -d -- "$file" replacer_tmp

  echo

done 3< <(find . -type f -print0)

(নন-পসিক্স প্রক্রিয়া বিকল্প ব্যবহার করে ফাইল লুপ এবং read -dসমর্থিত উদাহরণস্বরূপ bash।)

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