পূর্ণ ফাইল সিস্টেমে স্থান-পংক্তির লাইন মুছে ফেলা হচ্ছে?


11

অ্যাপ্লিকেশন বাগের কারণে এখনও নির্বিঘ্নিত হওয়ার কারণে আমার কাছে পুরো ডিস্ক সহ বেশ কয়েক'শ সার্ভার রয়েছে। একটি ফাইল রয়েছে যা নকল লাইনগুলিতে পূর্ণ হয়েছে - লগ ফাইল নয়, ভেরিয়েবল সংজ্ঞা সহ একটি ব্যবহারকারী পরিবেশ ফাইল (তাই আমি কেবল ফাইলটি মুছতে পারি না)।

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

যাইহোক, আমি যখন এটি সম্পূর্ণ ডিস্ক সহ সার্ভারে চেষ্টা করেছি, তখন আমি প্রায় নিম্নলিখিত ত্রুটিটি পেয়েছি (এটি মেমরি থেকে, অনুলিপি এবং আটকানো নয়):

sed: couldn't flush /path/to/file/sed8923ABC: No space left on deviceServerHostname

অবশ্যই, আমি জানি যে জায়গা নেই। এজন্য আমি জিনিস মুছে ফেলার চেষ্টা করছি! ( sedআমি যে কমান্ডটি ব্যবহার করছি তা একটি 4000+ লাইন ফাইলকে প্রায় 90 লাইনে হ্রাস করবে))

আমার sedআদেশ ন্যায্যsed -i '/myregex/d' /path/to/file/filename

পূর্ণ ডিস্ক সত্ত্বেও আমি এই আদেশটি প্রয়োগ করতে পারি এমন কোন উপায় আছে কি?

(এটি অবশ্যই স্বয়ংক্রিয় হওয়া উচিত, যেহেতু আমাকে তাড়াতাড়ি ফিক্স হিসাবে কয়েকশত সার্ভারে প্রয়োগ করা দরকার))

(স্পষ্টতই অ্যাপ্লিকেশন বাগটি সনাক্ত করা দরকার, তবে ইতিমধ্যে সার্ভারগুলি সঠিকভাবে কাজ করছে না ....)


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

/tmpনা-যেতে; এটি একই ফাইল সিস্টেমে on

আমি ডিস্কের স্থানটি খালি করার আগে, আমি পরীক্ষা করেছিলাম viএবং ফাইলটি খোলার :g/myregex/dসাথে সাথে চালানোর মাধ্যমে আমি লাইনগুলি মুছতে পারি এবং তারপরে পরিবর্তনগুলি সফলভাবে সংরক্ষণ করতে পারি :wq। কোনও টেম্প ফাইল রাখার জন্য পৃথক ফাইল সিস্টেমের অবলম্বন না করে এটি স্বয়ংক্রিয় করা সম্ভব হবে বলে মনে হচ্ছে .... (?)



1
sed -iপরিচালনা করার জন্য একটি অস্থায়ী অনুলিপি তৈরি করে। আমি সন্দেহ করি এটির edজন্য এটি আরও ভাল হবে, যদিও আমি প্রকৃত সমাধানের পক্ষে যথেষ্ট ধারণা রাখি না
এরিক রেনোফ

2
সঙ্গে edআপনি চালাতে চাই: printf %s\\n g/myregex/d w q | ed -s infileকিন্তু মনে রাখা কিছু বাস্তবায়নের এছাড়াও অস্থায়ী ফাইল ব্যবহার ঠিক sed(যদি আপনি চেষ্টা করে দেখতে পারেন , busybox ইডি - আমি যতদূর জানি এটি একটি অস্থায়ী ফাইল তৈরি করে না)
don_crissti

1
@ উইল্ডকার্ড - নির্ভরযোগ্যভাবে ডাব্লু / নয় echo। ব্যবহার printf। এবং sedশেষ লাইনে ফেলে আসা কিছু চর সংযোজন করুন যাতে আপনি পিছনের ফাঁকা স্থানগুলি হারাতে পারেন। এছাড়াও, আপনার শেলটি একটি একক কমান্ড-লাইনে পুরো ফাইলটি পরিচালনা করতে সক্ষম হতে হবে। এটিই আপনার ঝুঁকি - প্রথমে পরীক্ষা করুন। bashএটি বিশেষত খারাপ (আমি মনে করি এটি ডাব্লু / স্ট্যাক স্পেস করতে হবে?) এবং যে কোনও সময় আপনার উপর অসুস্থ হতে পারে। sedপ্রস্তাবিত দু'জন কমপক্ষে তাদের মধ্যে ভাল প্রভাব ফেলতে কার্নেলের পাইপ বাফারটি ব্যবহার করবে, তবে পদ্ধতিটি মোটামুটি একই। আপনার কমান্ড সাব জিনিসটি fileসেড ডাব্লু / ইন সফল কিনা তাও কেটে যাবে ।
মাইক্রজারভ

1
@ উইল্ডকার্ড - চেষ্টা করুন sed '/regex/!H;$!d;x' <file|{ read v && cat >file;}এবং যদি এটি কাজ করে তবে আমার উত্তরটি পড়ুন ''
মাইক্রজারভ

উত্তর:


10

-iবিকল্প সত্যিই মূল ফাইলটি প্রতিস্থাপন করা হয় না। এটি আউটপুট সহ একটি নতুন ফাইল তৈরি করে, তারপরে এটির নতুন নামকরণ করে। যেহেতু এই নতুন ফাইলটির জন্য আপনার ফাইল সিস্টেমে কোনও স্থান নেই, এটি ব্যর্থ।

আপনার নিজের স্ক্রিপ্টে এটি নিজেই করতে হবে তবে একটি নতুন ফাইল সিস্টেমে নতুন ফাইল তৈরি করুন।

এছাড়াও, আপনি যদি কেবল রেজিপক্সের সাথে মেলে এমন লাইনগুলি মুছতে থাকেন তবে আপনি এর grepপরিবর্তে ব্যবহার করতে পারেন sed

grep -v 'myregex' /path/to/filename > /tmp/filename && mv /tmp/filename /path/to/filename

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

আপনি যদি কোনও অস্থায়ী ফাইল ব্যবহার করতে না চান, আপনি মেমরিতে ফাইলের বিষয়বস্তুগুলি ক্যাশে করার চেষ্টা করতে পারেন:

file=$(< /path/to/filename)
echo "$file" | grep -v 'myregex' > /path/to/filename

1
এটি কি অনুমতি, মালিকানা এবং টাইমস্ট্যাম্পগুলি সংরক্ষণ করে? হয়তো rsync -a --no-owner --no-group --remove-source-files "$backupfile" "$destination"থেকে এখানে
Hastur

@ হাস্তুর - আপনার বোঝানোর অর্থ কি এই জিনিসটি sed -iসংরক্ষণ করে?
মাইক্রজারভ

2
@ হাস্তুর sed -iএই সমস্ত জিনিস সংরক্ষণ করে না। আমি কেবল এটি নিজের হাতে নেই এমন একটি ফাইল দিয়ে চেষ্টা করেছি, তবে আমার নিজের ডিরেক্টরিতে থাকা একটি ডিরেক্টরিতে এটি উপস্থিত রয়েছে এবং এটি আমাকে ফাইলটি প্রতিস্থাপন করতে দেয়। প্রতিস্থাপনটি আমার মালিকানাধীন, মূল মালিকের নয়।
বার্মার

1
@ রালফআরনকুইভিস্ট নিশ্চিত হওয়ার জন্য, আপনাকে এটি দুটি ধাপে করা দরকার:var=$(< FILE); echo "$FILE" | grep '^"' > FILE
বার্মার

1
@ বারমার - আপনি এটি কাজ করেন না - আপনি জানেন না যে আপনি সফলভাবে ইনপুটটি খোলেন। খুব অন্তত আপনি কি পারে v=$(<file)&& printf %s\\n "$v" >fileকিন্তু আপনি এমনকি ব্যবহার করবেন না &&। প্রশ্নকর্তা এটি কোনও স্ক্রিপ্টে চালানোর বিষয়ে কথা বলছেন - নিজের একটি অংশের সাহায্যে একটি ফাইলকে ওভাররাইটিং স্বয়ংক্রিয় করে তোলেন। কমপক্ষে আপনাকে বৈধতা দেওয়ার জন্য আপনার সাফল্যের সাথে ইনপুট এবং আউটপুট খুলতে হবে। এছাড়াও, শেলটি বিস্ফোরিত হতে পারে।
মাইকজার্ভ

4

এভাবেই sedকাজ করে। -i(স্থান সম্পাদনে) এর সাথে ব্যবহার করা sedহলে প্রক্রিয়াজাত ফাইলের নতুন সামগ্রীগুলির সাথে একটি অস্থায়ী ফাইল তৈরি করা হয়। সমাপ্ত হওয়ার পরে sed, অস্থায়ী ফাইলটির সাথে বর্তমান চলমান ফাইলটি প্রতিস্থাপন করে। ইউটিলিটি ফাইলটি জায়গায় জায়গায় সম্পাদনা করে না । প্রতিটি সম্পাদকের ঠিক এটাই আচরণ the

এটি শেলের মাধ্যমে আপনি নিম্নলিখিত কাজটি সম্পাদন করার মতো:

sed 'whatever' file >tmp_file
mv tmp_file file

এই মুহুর্তে sed, fflush()সিস্টেম কলের সাথে ত্রুটি বার্তায় উল্লিখিত ফাইলটিতে বাফার্ড ডেটা ফ্লাশ করার চেষ্টা করা হয় :

আউটপুট স্ট্রিমগুলির fflush()জন্য, প্রদত্ত আউটপুট বা স্ট্রিমের অন্তর্নিহিত রচনা ফাংশনটির মাধ্যমে আপডেট স্ট্রিমের জন্য সমস্ত ব্যবহারকারী-স্পেস বাফার ডেটা লিখতে বাধ্য করে।


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


3

এই প্রশ্নটি পোস্ট করার পর থেকে আমি শিখেছি যে exএটি পসিক্স-কমপ্লায়েন্ট প্রোগ্রাম। এটি প্রায় সর্বজনীনভাবে সিমিলিংযুক্ত vim, তবে যে কোনও উপায়ে নিম্নলিখিতটি (আমার মনে হয়) exফাইল-সিস্টেমের সাথে সম্পর্কিত একটি মূল বিষয় (পসিক্স স্পেসিফিকেশন থেকে নেওয়া):

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

"... যে কোনও ফাইলকে প্রভাবিত করবে ..." আমি বিশ্বাস করি যে ফাইল সিস্টেমে কিছু রাখা (মোটামুটি এমনকি একটি টেম্প ফাইলও) "কোনও ফাইলকে প্রভাবিত করে" বলে গণ্য করবে। হতে পারে?*

অনলাইনে পাওয়া সাধারণ স্ক্রিপ্টযুক্ত ব্যবহারের তুলনায় (যা স্পেসিফিক কমান্ডের সাথে আবদ্ধ থাকে) তুলনায় যখন তার উদ্দেশ্যযুক্ত পোর্টেবল ব্যবহার সম্পর্কে কিছু "গোটচ" নির্দেশ করে তার জন্য পসিক্স স্পেসিফিকেশনগুলিরex সাবধানতার সাথে অধ্যয়ন indicateexvim

  1. পসিক্স +cmdঅনুসারে বাস্তবায়ন optionচ্ছিক।
  2. একাধিক -cবিকল্পের অনুমতি দেওয়াও alচ্ছিক ।
  3. গ্লোবাল কমান্ড :gপরের অ-পালানো নিউলাইন পর্যন্ত সমস্ত কিছু "খায়" (এবং তাই এটি প্রতিটি ম্যাচ শেষে একবারের পরিবর্তে রেজেক্সের সন্ধানের পরে চালায়)। সুতরাং -c 'g/regex/d | x'কেবলমাত্র একটি উদাহরণ মুছুন এবং তারপরে ফাইলটি প্রস্থান করুন।

সুতরাং আমি যা গবেষণা করেছি তার অনুসারে, নির্দিষ্ট রেজেক্সের সাথে মিলে থাকা সমস্ত লাইন মুছে ফেলার জন্য একটি পূর্ণ ফাইল সিস্টেমের মধ্যে কোনও ফাইল সম্পাদনা করার জন্য পসিক্স-অনুবর্তী পদ্ধতিটি হ'ল:

ex -sc 'g/myregex/d
x' /path/to/file/filename

আপনার বাফারে ফাইল লোড করার পর্যাপ্ত মেমরির সরবরাহ করার সাথে এটি কাজ করা উচিত।

* যদি আপনি এমন কোনও কিছু খুঁজে পান যা অন্যথায় নির্দেশ করে তবে দয়া করে মন্তব্যে এটি উল্লেখ করুন।


2
কিন্তু প্রাক্তন tmpfiles লিখে ... সর্বদা। এটি নির্দিষ্টভাবে তার বাফারগুলিকে ডিস্কে পর্যায়ক্রমে লিখতে চায়। এমনকি ডিস্কে টিএমপি ফাইল বাফারগুলি সনাক্ত করার জন্য নির্দিষ্ট কমান্ড রয়েছে।
মাইক্রজারভের

@ উইলকার্ড ভাগ করে নেওয়ার জন্য ধন্যবাদ, আমি এসও তে একই পোস্টে আবার লিঙ্ক করেছি । আমি ধরে নিলাম ex +g/match/d -scx fileপসিক্স-কমপ্লায়েন্টও কি?
কেনারব

@ টেনরব, আমার চশমা পড়ার মত নয়, উপরের উত্তরে আমার পয়েন্ট 1 দেখুন। পসিক্সের সঠিক উদ্ধৃতিটি হ'ল "প্রাক্তন ইউটিলিটিটি '-' এর অনির্দিষ্ট ব্যবহার ব্যতীত এক্সবিডি ইউটিলিটি সিনট্যাক্স গাইডলাইনগুলিকে মেনে চলবে এবং সেই '+' বিকল্পের ডেলিমিটার হিসাবে স্বীকৃত হতে পারে এবং '-' হিসাবেও হতে পারে ।"
ওয়াইল্ডকার্ড

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

@ জি-ম্যান, আমি আসলে মনে করি আপনি ঠিক বলেছেন; আমার প্রাথমিক ব্যাখ্যা সম্ভবত ইচ্ছুক চিন্তাভাবনা ছিল। যাইহোক, ফাইলটি একটি সম্পূর্ণ ফাইল সিস্টেমে vi কাজ করার পরে, আমি বিশ্বাস করি যে বেশিরভাগ ক্ষেত্রে এটি কাজ করে exmaybe যদিও এটি কোনও জিনরমাস ফাইলের জন্য নয়। sed -iফাইল সাইজ নির্বিশেষে একটি সম্পূর্ণ ফাইল সিস্টেমের কাজ করে না।
ওয়াইল্ডকার্ড

2

পাইপ ব্যবহার করুন, লুক!

ফাইল পড়ুন | ফিল্টার | প্রতিত্তর লিখুন

sed 's/PATTERN//' BIGFILE | dd of=BIGFILE conv=notrunc

এই ক্ষেত্রে sedএকটি নতুন ফাইল তৈরি করে না এবং কেবল আউটপুট পাইপ দেয় ddযা একই ফাইলটি খোলে । অবশ্যই একটি grepবিশেষ ক্ষেত্রে ব্যবহার করতে পারেন

grep -v 'PATTERN' BIGFILE | dd of=BIGFILE conv=notrunc

তারপরে বাকিগুলি কেটে ফেলুন

dd if=/dev/null of=BIGFILE seek=1 bs=BYTES_OF_SED_OUTPUT

1
আপনি প্রশ্নের "সম্পূর্ণ ফাইল সিস্টেম" লক্ষ্য করেছেন ?
ওয়াইল্ডকার্ড

1
@ উইল্ডকার্ড, sedসর্বদা টেম্প ফাইল ব্যবহার করে? grepযাই হোক না কেন
লেবেন গ্লেবেন

এটি spongeকমান্ডের বিকল্প বলে মনে হচ্ছে । হ্যাঁ, sedসঙ্গে -iসবসময় lilke 000 অধিকার সঙ্গে "seduyUdmw" ফাইল তৈরি করে।
পাবলো এ

1

অন্যান্য উত্তরে যেমন উল্লেখ করা হয়েছে, একই ডিরেক্টরিতেsed -i ফাইলটি একটি নতুন ফাইলে অনুলিপি করে , প্রক্রিয়াটিতে পরিবর্তন করে এবং তারপরে নতুন ফাইলটিকে মূলের উপরে নিয়ে যাওয়া কাজ করে। এ কারণেই এটি কাজ করে না।  (মূল লাইন সম্পাদক) কিছুটা অনুরূপ পদ্ধতিতে কাজ করে, তবে, আমি যখন শেষবার যাচাই করেছিলাম এটি স্ক্র্যাচ ফাইলের জন্য ব্যবহার করে। আপনি যদি পূর্ণ হয়ে থাকেন তার থেকে আলাদা কোনও ফাইল সিস্টেমে থাকেন তবে আপনার পক্ষে কাজটি করতে পারে।ed/tmp/tmped

এটি চেষ্টা করুন (আপনার ইন্টারেক্টিভ শেল প্রম্পটে):

$ এড / পাথ / টু / ফাইল / ফাইল নাম
পি
জি / মাইরেজেক্স / ডি
W
কুই

P(যা একটি হল রাজধানী পি) কঠোরভাবে প্রয়োজন নেই। এটি অনুরোধ চালু করে; এটি ছাড়া, আপনি অন্ধকারে কাজ করছেন এবং কিছু লোক এই উদ্বেগজনক বলে মনে করেন। wএবং qহয় W আচার এবং কুই UIT।

edক্রিপ্টিক ডায়াগনস্টিকসের জন্য কুখ্যাত। যেকোনো সময়ে কিছু অন্যান্য যেগুলি বিজ্ঞপ্তি (যা প্রদর্শন করা হয় তাহলে *পরিষ্কারভাবে সফল অপারেশন (এর একটি নিশ্চিতকরণ যে) অথবা কিছু বিশেষ করে যদি এটি একটি রয়েছে ?,) না (সঙ্গে ফাইলটি লিখতে w)। সবে ছাড়ুন ( q)। যদি এটি আপনাকে ছাড়তে না দেয় তবে qআবার বলার চেষ্টা করুন ।

যদি আপনার /tmpডিরেক্টরিটি পূর্ণ ফাইল সিস্টেমে থাকে তবে (বা যদি এর ফাইল সিস্টেমটিও পূর্ণ থাকে) তবে কোথাও কোথাও কিছু জায়গা সন্ধান করার চেষ্টা করুন। বিশৃঙ্খলাটিতে একটি tmpfs বা একটি বাহ্যিক স্টোরেজ ডিভাইস (উদাহরণস্বরূপ, একটি ফ্ল্যাশ ড্রাইভ) মাউন্ট করার কথা বলা হয়েছে; কিন্তু, যদি আপনি একাধিক ফাইল সিস্টেম আছে, এবং তারা না সব পূর্ণ, আপনি কেবল অন্যান্য বিদ্যমান বেশী এক ব্যবহার করতে পারেন। বিশৃঙ্খলা অন্য ফাইল সিস্টেমে ফাইল (গুলি) অনুলিপি করে, সেগুলি এখানে (দিয়ে sed) সম্পাদনা করে এবং তারপরে সেগুলি অনুলিপি করার পরামর্শ দেয়। এই মুহুর্তে, এটি সবচেয়ে সহজ সমাধান হতে পারে। তবে বিকল্পটি হ'ল এমন একটি ফাইল সিস্টেমে একটি লিখনযোগ্য ডিরেক্টরি তৈরি করা যায় যাতে কিছু মুক্ত স্থান থাকে, TMPDIRসেই ডিরেক্টরিতে নির্দেশ করতে পরিবেশের পরিবর্তনশীল সেট করে , এবং তারপরে চালানো হয় ed। (প্রকাশ: এটি কাজ করবে কিনা তা সম্পর্কে আমি নিশ্চিত নই, তবে এটি ক্ষতি করতে পারে না))

আপনি একবার edকাজ করা হয়ে গেলে , আপনি এটি করে এটি স্বয়ংক্রিয় করতে পারেন

এড ফাইলের নাম << ইওএফ
জি / মাইরেজেক্স / ডি
W
কুই
ফাইলের শেষে

একটি স্ক্রিপ্টে। বা , ডন_ক্রিসিটি দ্বারা প্রস্তাবিত হিসাবে।printf '%s\n' 'g/myregex/d' w q | ed -s filename


হুম। পৃথক ফাইল সিস্টেমের পরিবর্তে মেমরিটি ব্যবহার করা যেতে পারে (একই সাথে edবা সাথে ex) একই জিনিসটিও করা যেতে পারে ? এটাই আমি সত্যিই যাচ্ছিলাম (এবং যে কারণে আমি কোনও উত্তর গ্রহণ করি নি।)
ওয়াইল্ডকার্ড

হুম। আমি বুঝতে পারার চেয়ে এটি আরও জটিল হতে পারে। edবহু বছর আগে আমি এর উত্সটি অধ্যয়ন করেছি । এখনও 16-বিট কম্পিউটারের মতো জিনিস ছিল, যার উপর প্রসেসগুলি 64K (!) ঠিকানার জায়গার মধ্যে সীমাবদ্ধ ছিল, তাই সম্পূর্ণ ফাইলটিকে মেমরির মধ্যে পড়ার সম্পাদকের ধারণাটি একটি স্টার-স্টার্টার ছিল না। সেই থেকে অবশ্যই মেমরিটি আরও বড় হয়েছে - তবে ডিস্ক এবং ফাইল রয়েছে have যেহেতু ডিস্কগুলি এত বড়, লোকেরা /tmpস্থানের বাইরে চলে যাওয়ার সংকটটি মোকাবেলা করার প্রয়োজন মনে করে না । আমি কেবলমাত্র একটি সাম্প্রতিক সংস্করণের উত্স কোডটি edদেখেছি এবং এটি এখনও মনে হচ্ছে ... (চালানো)
জি-ম্যান বলে

(চালিয়ে যাওয়া) ... শর্তহীনভাবে একটি "টেম্প ফাইল" হিসাবে "সম্পাদনা বাফার" প্রয়োগ করতে - এবং আমি কোনও ইঙ্গিত পাই না যে কোনও সংস্করণ ed( exবা vi) বাফারের স্মৃতিতে রাখার জন্য একটি বিকল্প প্রস্তাব দেয়।  অন্যদিকে, এডি এবং vi সহ পাঠ্য সম্পাদনা - অধ্যায় 11: পাঠ্য প্রক্রিয়াকরণ - দ্বিতীয় খণ্ড: রেড হ্যাট লিনাক্স এক্সপ্লোর করা - রেড হ্যাট লিনাক্স 9 পেশাদার গোপনীয়তা - লিনাক্স সিস্টেমগুলি বলেছে যে edসম্পাদনা বাফার মেমরিতে বাস করে, ... (Cont'd )
জি-ম্যান বলছেন 'পুনরায় ইনস্টল করুন মনিকা'

(কনটড) ... এবং ইউএনআইএক্স ডকুমেন্ট প্রসেসিং এবং টাইপসেটিং দ্বারা বালাসুব্রাহ্মণিয়াম শ্রীনিবাসন একই বিষয়ে বলেছেন vi(যা একই প্রোগ্রাম হিসাবে ex)। আমি বিশ্বাস করি যে তারা কেবল opালু, অনর্থক শব্দ ব্যবহার করছে - তবে, এটি যদি ইন্টারনেটে থাকে (বা মুদ্রণে) থাকে তবে এটি অবশ্যই সত্য হতে হবে, তাই না? আপনি আপনার অর্থ প্রদান এবং আপনি নিজের পছন্দ গ্রহণ।
জি-ম্যান

তবে যাইহোক, আমি একটি নতুন উত্তর যুক্ত করেছি।
জি-ম্যান

1

আপনি যদি আপনার অফসেটে বাইট গণনাটি পেতে পারেন এবং আপনার লাইনগুলি একটি শুরু বিন্দু থেকে শেষ অবধি ঘটে তবে আপনি ফাইলটি খুব সহজেই কাটাতে পারবেন।

o=$(sed -ne'/regex/q;p' <file|wc -c)
dd if=/dev/null of=file bs="$o" seek=1

অন্যথায় যদি আপনার অন্য ${TMPDIR:-/tmp}কোনও ফাইল সিস্টেমে থাকে তবে সম্ভবত:

{   cut -c2- | sed "$script" >file
} <file <<FILE
$(paste /dev/null -)
FILE

কারণ (বেশিরভাগ) শেলগুলি এখানে মুছে ফেলা টেম্পল ফাইলগুলিতে তাদের নথিগুলি রাখে। এটি পুরোপুরি নিরাপদ যতক্ষণ না <<FILEবর্ণনাকারী শুরু থেকে শেষ পর্যন্ত বজায় থাকে এবং ${TMPDIR:-/tmp}আপনার প্রয়োজন মতো স্থান থাকে।

টেম্প ফাইলগুলি ব্যবহার না করে এমন শেলগুলি পাইপ ব্যবহার করে এবং তাই এইভাবে ব্যবহার করা নিরাপদ নয়। এই শাঁস সাধারণত ashডেরাইভেটিভস পছন্দ busybox, dash, বাসদ sh- zsh,bash , ksh, এবং বোর্ন শেল অবশ্য সব ব্যবহার টেম্প ফাইল।

স্পষ্টতই আমি খুব ভালো কিছু করার জন্য গত জুলাইয়ে একটি ছোট শেল প্রোগ্রাম লিখেছিলাম


যদি /tmp ব্যবহারযোগ্য না হয়, তবে যতক্ষণ আপনি ফাইলটিকে মেমরিতে ফিট করতে পারেন তেমন কিছু ...

sed 'H;$!d;x' <file | { read v &&
sed "$script" >file;}

... একটি সাধারণ কেস হিসাবে অন্তত নিশ্চিত করা উচিত যে ফাইলটি sedইন / আউট ফাইল কেটে দেওয়ার চেষ্টা করার আগে প্রথম প্রক্রিয়াটি পুরোপুরি বাফার করেছিল ।

আরও লক্ষ্যযুক্ত - এবং দক্ষ - সমাধান হতে পারে:

sed '/regex/!H;$!d;x' <file|{ read v && cat >file;}

... কারণ এটি যে কোনও উপায়ে মুছে ফেলতে চেয়েছিল বোঝা লাইনগুলিকে বিরক্ত করবে না।

সাধারণ ক্ষেত্রে একটি পরীক্ষা:

{   nums=/tmp/nums
    seq 1000000 >$nums
    ls -lh "$nums"
    wc -l  "$nums"
    sed 'H;$!d;x' <$nums | { read script &&  ### read always gets a blank
    sed "$script" >$nums;}
    wc -l  "$nums"
    ls -lh "$nums"
}

-rw-r--r-- 1 mikeserv mikeserv 6.6M Dec 22 20:26 /tmp/nums
1000000 /tmp/nums
1000000 /tmp/nums
-rw-r--r-- 1 mikeserv mikeserv 6.6M Dec 22 20:26 /tmp/nums

আমি স্বীকার করি যে এর আগে আমি আপনার উত্তরটি বিশদভাবে পড়িনি, কারণ এটি অকার্যকর (আমার জন্য) সমাধানগুলির সাথে শুরু হয় যা বাইট গণনা জড়িত (বহু সার্ভারগুলির মধ্যে প্রত্যেকের মধ্যে পৃথক) এবং /tmpযা একই ফাইল সিস্টেমে রয়েছে। আমি আপনার দ্বৈত sedসংস্করণ পছন্দ। আমি মনে করি বার্মার এবং আপনার উত্তরগুলির সংমিশ্রণটি সম্ভবত সেরা হবে, এরকম কিছু: myvar="$(sed '/myregex/d' < file)" && [ -n "$myvar" ] && echo "$myvar" > file ; unset myvar (এই ক্ষেত্রে আমি অনুমান করা নতুন লাইনের সংরক্ষণের বিষয়ে চিন্তা করি না))
ওয়াইল্ডকার্ড

2
@ উইল্ডকার্ড - এটি হতে পারে। তবে আপনি শেলটি ডাটাবেসের মতো ব্যবহার করতে পারবেন না। sed| ইতিমধ্যে পুরো ফাইলটি বাফার না করে এবং আউটপুটে এর সবগুলি লেখা শুরু করতে প্রস্তুত না হলে catউপরের জিনিসটি কখনই আউটপুট sedখোলায় না। ফাইল বাফার করার চেষ্টা করে এবং ব্যর্থ হলে - readসফল কারণ খুঁজে বের করে উপর ফাইলের শেষে নয় |নল আগে এটা তার প্রথম সম্পর্কে newline পড়ে এবং তাই cat >out কখনো ঘটবে তার সময় পর্যন্ত সম্পূর্ণরূপে স্মৃতি থেকে এটি লিখতে। একটি ওভারফ্লো বা এর মতো কিছু কেবল ব্যর্থ হয়। এছাড়াও পুরো পাইপলাইনটি প্রতিবার সাফল্য বা ব্যর্থতা দেয়। এটি কোনও ভারে সংরক্ষণ করা আরও ঝুঁকিপূর্ণ।
মাইকজার্ভ

@ উইল্ডকার্ড - যদি আমি সত্যিই এটি একটি চলকতেও চাইতাম তবে আমি মনে করি আইডিটি এটি পছন্দ করে: file=$(sed '/regex/!H;$!d;x' <file | read v && tee file) && cmp - file <<<"$file" || shiteতাই আউটপুট ফাইল এবং ভারগুলি একই সাথে লেখা হবে, যা হয় বা কার্যকর ব্যাকআপ তৈরি করবে, এটিই কেবল কারণ যা আপনি চান আপনার প্রয়োজনের চেয়ে জিনিসগুলিকে আরও জটিল করুন।
মাইকজার্ভ

@ মাইকজার্ভ: আমি এখন ওপি'র মতো একই সমস্যাটি মোকাবিলা করছি এবং আমি আপনার সমাধানটি সত্যিই দরকারী বলে মনে করি। তবে আমি আপনার উত্তরের ব্যবহার read scriptএবং বুঝতে পারছি না read v। আপনি যদি এ সম্পর্কে আরও বিস্তারিত বলতে পারেন তবে আমি অনেক প্রশংসা করব, ধন্যবাদ!
sylye

1
@ সাইল্লি - আপনার ফাইলের যে কোনও অংশটি আপনি চেয়েছিলেন তা লক্ষ্য করতে আপনি $scriptযে sedস্ক্রিপ্টটি ব্যবহার করবেন তা হ'ল ; এটির স্ক্রিপ্ট যা আপনাকে স্রোতে চায় এমন শেষ ফলাফল দেয়। vখালি লাইনের জন্য কেবল স্থানধারক। একটি bashশেল এটা প্রয়োজনীয় কারণ নয় bashস্বয়ংক্রিয়ভাবে ব্যবহার করবে $REPLYযদি আপনি এখানে কিছু উল্লেখ না তার উপকার মধ্যে শেল পরিবর্তনশীল, কিন্তু POSIXly আপনি সবসময় তাই করা উচিত। আমি আনন্দিত আপনি উপায় দ্বারা এটি দরকারী। এটির জন্য শুভকামনা। আপনার যদি গভীরতার কিছু দরকার হয় তবে ইম মাইকজার্ভ @ জিমেইল। আমার কয়েক দিনের মধ্যে আবার একটি কম্পিউটার থাকা উচিত
মাইকসার্ভ

0

এই উত্তরটি এই অন্যান্য উত্তর এবং এই অন্যান্য উত্তর থেকে ধারণা ধার করে তবে সেগুলি তৈরি করে, এমন একটি উত্তর তৈরি করে যা আরও সাধারণভাবে প্রযোজ্য:

num_bytes = $ (সেড '/ myregex / d' / পাথ / থেকে / ফাইল / ফাইল নাম সি)
সেড '/ মাইরেজেক্স / ডি' / পাথ / টু / ফাইল / ফাইলনাম 1 <> / পাথ / টু / ফাইল / ফাইলনাম 
ডিডি যদি = / dev / নাল = / পাথ / টু / ফাইল / ফাইল নেম বিএস = "$ নাম_বাইটস" সন্ধান করে = 1

প্রথম লাইনটি sedস্ট্যান্ডার্ড আউটপুট (এবং কোনও ফাইলে নয়) লেখা আউটপুট দিয়ে কমান্ড চালায় ; wcচরিত্রগুলি গণনা করার জন্য বিশেষত, একটি পাইপ । দ্বিতীয় লাইনটি sedস্ট্যান্ডার্ড আউটপুটে লিখিত আউটপুট সহ কমান্ডও চালায় , যা এই ক্ষেত্রে রিড / রাইট ওভাররাইট (কোনও কাণ্ড নয়) মোডে ইনপুট ফাইলটিতে পুনর্নির্দেশ করা হয়, যা এখানে আলোচনা করা হয়েছে । এটি করা কিছুটা বিপজ্জনক জিনিস; এটি কেবল তখনই নিরাপদ যখন ফিল্টার কমান্ড কখনই ডেটার পরিমাণ (পাঠ্য) বাড়ায় না; অর্থাত, এটি পড়ার প্রতিটি এন বাইটের জন্য , এটি এন বা কম বাইট লিখে । এটি অবশ্যই sed '/myregex/d'আদেশের পক্ষে সত্য ; এটি যে পংক্তিতে পড়েছে তার জন্য এটি একই লাইনটি লিখে দেয় বা কিছুই না। (অন্যান্য উদাহরণ:s/foo/fu/বা s/foo/bar/নিরাপদ হতে পারে, কিন্তু s/fu/foo/এবং s/foo/foobar/হবে না।)

উদাহরণ স্বরূপ:

$ cat filename
It was
a dark and stormy night.
$ sed '/was/d' filename 1<> filename
$ cat filename
a dark and stormy night.
night.

কারণ এই 32 বাইট ডেটা:

I  t     w  a  s \n  a     d  a  r  k     a  n  d     s  t  o  r  m  y     n  i  g  h  t  . \n

এই 25 টি অক্ষরের সাথে ওভাররাইট করা হয়েছে:

a     d  a  r  k     a  n  d     s  t  o  r  m  y     n  i  g  h  t  . \n

শেষে সাতটি বাইট night.\nরেখে গেছে

অবশেষে, ddকমান্ডটি নতুন, স্ক্রাবড ডেটা (এই উদাহরণে 25 বাইট) এর শেষে সন্ধান করে এবং বাকী ফাইলটি সরিয়ে দেয়; অর্থাত্‍ এটি পয়েন্টে ফাইলটি কেটে দেয়।


যদি, কোনও কারণে, 1<>কৌশলটি কাজ করে না, আপনি করতে পারেন do

সেড '/ মাইরেজেক্স / ডি' / পাথ / টু / ফাইল / ফাইল নাম | dd of = / path / to / file / filename কনভ = notrunc

এছাড়াও, নোট করুন, যতক্ষণ না আপনি যা করছেন সমস্তগুলি লাইনগুলি সরিয়ে ফেলা হচ্ছে, আপনার যা যা প্রয়োজন তা হ'ল grep -v myregex( বার্মার দ্বারা নির্দেশিত )।


-3

সেড-আই 'ডি' / পাথ / টু / ফাইল / ফাইল নাম


1
ওহে! আপনার সমাধানটি কীভাবে প্রাসঙ্গিক এবং প্রশ্নটির উত্তর দেয় সে সম্পর্কে যতটা প্রাসঙ্গিক তার সাথে আরও বিস্তারিতভাবে ব্যাখ্যা করা ভাল।
ধাগ

2
এটি একটি ভয়াবহ অ-উত্তর। (ক) এটি আমার আসল কমান্ডের মতো একটি সম্পূর্ণ ফাইল সিস্টেমে ব্যর্থ হবে; (খ) যদি এটি সফল হয়, তবে এটি আমার রেজেক্সের সাথে মেলে কেবল লাইনগুলির চেয়ে পুরো ফাইলটি খালি করে দেবে।
ওয়াইল্ডকার্ড
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.