জায়গাটিতে কোনও ফাইল সংশোধন করার কোনও উপায় আছে কি?


54

আমার কাছে মোটামুটি বড় ফাইল (৩৫ জিবি) রয়েছে এবং আমি এই ফাইলটি সিটুতে ফিল্টার করতে চাই (যেমন আমার কাছে অন্য কোনও ফাইলের জন্য পর্যাপ্ত ডিস্কের জায়গা নেই), বিশেষত আমি গ্রেপ করে কিছু প্যাটার্ন উপেক্ষা করতে চাই - এই উপায়টির উপায় কি? অন্য ফাইল ব্যবহার না করে এটি করবেন?

ধরা যাক আমি foo:উদাহরণস্বরূপ সমস্ত লাইন ফিল্টার করতে চাই ...


3
@ শেপাপাং: আমার মনে হয় তিনি আবার একই ফাইলটিতে লিখতে চান।
ফাহিম মিঠা

5
"ইন সিটু" হ'ল ল্যাটিন বাক্যাংশ যার অর্থ "জায়গায়"। আক্ষরিক অর্থে, "পজিশনে"।
ফাহিম মিঠা

3
সেক্ষেত্রে প্রশ্নটি আরও স্পষ্ট হওয়া উচিত, এর মতো কোনও স্থানের জায়গায় কোনও ফাইল পরিবর্তন করার উপায় আছে ?
tshepang

5
@ শেপাপাং, "ইন সিটু" হ'ল ইংরেজিতে একেবারে প্রচলিত একটি সাধারণ বাক্যাংশ যা হুবহু বর্ণনা করার জন্য - আমি ভেবেছিলাম শিরোনামটি মোটামুটি স্ব-বর্ণনামূলক ছিল ... @ গিলিস, আমি আরও বেশি ডিস্কের জায়গার জন্য অপেক্ষা করা আরও সহজ, আবিষ্কার করেছি! ;)
নিম

2
@Nim: ওয়েল, আমি মনে করি ইন-জায়গা চেয়ে বেশি দেখা যায় স্থানেই
tshepang

উত্তর:


41

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

যেহেতু আপনি ইনপুট থেকে লাইনগুলি ফিল্টার করছেন, আউটপুট ফাইল রাইটিং অবস্থান সর্বদা পঠনের অবস্থানের চেয়ে কম হওয়া উচিত। এর অর্থ হল নতুন আউটপুট সহ আপনার ইনপুটটি দূষিত করা উচিত নয়।

তবে, এমন একটি প্রোগ্রাম সন্ধান করা যা সমস্যা is খোলা অবস্থায় আউটপুট ফাইলকে ছাঁটাই করে না dd(1)এমন বিকল্প রয়েছে conv=notrunc, তবে এটি শেষে ফাইলের মূল বিষয়বস্তুগুলি ছেড়ে যাওয়ার পরে (যেমন একটি কমান্ডের সাহায্যে grep pattern bigfile | dd of=bigfile conv=notrunc) কেটে যাবে না

যেহেতু এটি সিস্টেম কল দৃষ্টিকোণ থেকে খুব সহজ, আমি একটি ছোট প্রোগ্রাম লিখেছি এবং এটি একটি ছোট (1MiB) পূর্ণ লুপব্যাক ফাইল সিস্টেমে পরীক্ষা করেছি। এটি আপনি যা চেয়েছিলেন তা করেছে তবে আপনি প্রথমে অন্য কয়েকটি ফাইলের সাথে এটি পরীক্ষা করতে চান। এটি সর্বদা একটি ফাইল ওভাররাইটিং ঝুঁকিপূর্ণ হতে চলেছে।

overwrite.c

/* This code is placed in the public domain by camh */

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>

int main(int argc, char **argv)
{
        int outfd;
        char buf[1024];
        int nread;
        off_t file_length;

        if (argc != 2) {
                fprintf(stderr, "usage: %s <output_file>\n", argv[0]);
                exit(1);
        }
        if ((outfd = open(argv[1], O_WRONLY)) == -1) {
                perror("Could not open output file");
                exit(2);
        }
        while ((nread = read(0, buf, sizeof(buf))) > 0) {
                if (write(outfd, buf, nread) == -1) {
                        perror("Could not write to output file");
                        exit(4);
                }
        }
        if (nread == -1) {
                perror("Could not read from stdin");
                exit(3);
        }
        if ((file_length = lseek(outfd, 0, SEEK_CUR)) == (off_t)-1) {
                perror("Could not get file position");
                exit(5);
        }
        if (ftruncate(outfd, file_length) == -1) {
                perror("Could not truncate file");
                exit(6);
        }
        close(outfd);
        exit(0);
}

আপনি এটি হিসাবে ব্যবহার করবেন:

grep pattern bigfile | overwrite bigfile

আপনার চেষ্টা করার আগে আমি অন্যকে মন্তব্য করার জন্য এটি বেশিরভাগই পোস্ট করছি। সম্ভবত অন্য কেউ এমন একটি প্রোগ্রাম সম্পর্কে জানেন যা এরকম কিছু করে যা আরও পরীক্ষিত হয়।


আমি দেখতে চেয়েছিলাম এটির জন্য কিছু না লিখে আমি পালাতে পারি কিনা! :) আমার ধারণা এই কৌশলটি করবে! ধন্যবাদ!
নিম

2
সি জন্য +1; এটি কাজ করে বলে মনে হচ্ছে, তবে আমি একটি সম্ভাব্য সমস্যা দেখতে পাচ্ছি: ডানটি একই ফাইলটিতে লেখার সময় বাম দিক থেকে ফাইলটি পড়া হচ্ছে এবং আপনি দুটি প্রক্রিয়া সমন্বয় না করলে আপনার সম্ভাব্য সমস্যাগুলি একইরূপে ওভাররাইট হয়ে যাবে ব্লক। ফাইল অখণ্ডতার পক্ষে ছোট ব্লকের আকার ব্যবহার করা আরও ভাল হবে কারণ বেশিরভাগ মূল সরঞ্জামগুলি সম্ভবত 8192 ব্যবহার করবে This এটি দ্বন্দ্ব এড়াতে পর্যাপ্ত প্রোগ্রামটি ধীর করতে পারে (তবে গ্যারান্টি দিতে পারে না)। সম্ভবত মেমরির বৃহত্তর অংশগুলি পড়ুন (সমস্ত নয়) এবং ছোট ব্লকে লিখুন। একটি ন্যানোস্লিপ (2) / ইউএসপ (3) যোগ করতে পারে।
আর্জেজ

4
@ আর্জেজ: ব্লকগুলিতে লেখা হয় না। যদি আপনার পঠন প্রক্রিয়াটি 2 বাইট পড়েছে এবং আপনার লেখার প্রক্রিয়াটি 1 বাইট লিখে ফেলেছে তবে কেবল প্রথম বাইট পরিবর্তন হবে এবং পঠন প্রক্রিয়াটি অপরিবর্তিত অবস্থায় মূল বিষয়বস্তু সহ 3 বাইটে পড়া চালিয়ে যেতে পারে। যেহেতু grepএটি পড়ার চেয়ে বেশি ডেটা আউটপুট দেবে না, তাই লেখার অবস্থান সবসময় পঠনের অবস্থানের পিছনে থাকা উচিত। আপনি যেমন পড়ার সমান হারে লিখছেন তবুও এটি ঠিক থাকবে। গ্রেপের পরিবর্তে এর সাথে পচা 13 চেষ্টা করুন এবং তারপরে আবার। md5sum এর আগের এবং পরে এবং আপনি এটি দেখতে পাবেন।
ক্যাম এছ

6
খুশী হলাম। জোয়ে হেসের মুর্যুতে এটি একটি মূল্যবান সংযোজন হতে পারে । আপনি ব্যবহার করতে পারেনdd , কিন্তু এটি জটিল।
গিলস 21 '

'গ্রেপ প্যাটার্ন বিগফিল | ওভাররাইট বিগফিল '- আমি ত্রুটি ছাড়াই এই কাজটি পেয়েছি, তবে যা আমি বুঝতে পারি না তা হ'ল - অন্য কোনও পাঠ্যের সাথে প্যাটার্নটিতে কী রয়েছে তা প্রতিস্থাপনের প্রয়োজন নেই? সুতরাং এটির মতো কিছু হওয়া উচিত নয়: 'গ্রেপ প্যাটার্ন বিগফিল | ওভাররাইট / রিপ্লেস-টেক্সট / বিগফিল '
আলেকজান্ডার মিলস

20

আপনি sedজায়গায় ফাইল সম্পাদনা করতে ব্যবহার করতে পারেন (তবে এটি মধ্যবর্তী অস্থায়ী ফাইল তৈরি করে):

ধারণকারী সমস্ত লাইন অপসারণ করতে foo:

sed -i '/foo/d' myfile

সমস্ত লাইন ধারণ করে রাখতে foo:

sed -i '/foo/!d' myfile

আকর্ষণীয়, এই টেম্প ফাইলটি যদিও মূলটির মতো একই আকারের হওয়া দরকার?
নিম

3
হ্যাঁ, তাই সম্ভবত এটি ভাল না।
pjc50

17
এটি দ্বিতীয় ফাইল তৈরি করার পর থেকে ওপি এটিই জিজ্ঞাসা করছে না।
আর্জেজ

1
এই সমাধান শুধুমাত্র পাঠযোগ্য ফাইল সিস্টেম, উপর ব্যর্থ হবে যেখানে "শুধুমাত্র পাঠযোগ্য" মানে হল আপনার $HOME হবে লিখনযোগ্য, কিন্তু /tmpকরা হবে না -কেবল পঠন (ডিফল্ট অনুসারে)। উদাহরণস্বরূপ, আপনার যদি উবুন্টু থাকে এবং আপনি পুনরুদ্ধার কনসোলটি বুট করেন তবে সাধারণত এটি হয়। এছাড়াও, এখানে নথি অপারেটর <<<সেখানে পারেন কাজ করবে না, যেমন এটি প্রয়োজন /tmpহতে দ / W কারণ এটি পাশাপাশি সেখানে একটি অস্থায়ী ফাইল লিখতে হবে। (সিএফ। এই প্রশ্নটি একটি strace'ডি আউটপুট সহ )
সিনট্যাক্সারর

হ্যাঁ এটি আমার পক্ষে কাজ করবে না, আমি চেষ্টা করেছি এমন সমস্ত সেড কমান্ড বর্তমান ফাইলটি নতুন একটি ফাইলের সাথে প্রতিস্থাপন করবে (- - স্থানের পতাকা থাকা সত্ত্বেও)
আলেকজান্ডার মিলস

19

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

বেশিরভাগ ইউনিক্স সরঞ্জাম কেবল কোনও ফাইলগুলিতে সংযোজন বা এটি ছাঁটাইয়ের কোনও বিকল্প দেয়, এটির ওভাররাইটের কোনও সম্ভাবনা নেই। স্ট্যান্ডার্ড টুলবক্সের একটি ব্যতিক্রম হ'ল dd, যা এর আউটপুট ফাইলটি ছাঁটাই না করতে বলা যেতে পারে। সুতরাং পরিকল্পনাটি হ'ল কমান্ডটি ফিল্টার করা dd conv=notrunc। এটি ফাইলের আকার পরিবর্তন করে না, তাই আমরা নতুন সামগ্রীর দৈর্ঘ্যও ধরি এবং ফাইলটিকে সেই দৈর্ঘ্যে (আবার দিয়ে dd) ছাঁটাই করি । মনে রাখবেন যে এই কাজটি সহজাতভাবে শক্তিশালী নয় - যদি কোনও ত্রুটি দেখা দেয় তবে আপনি নিজেরাই।

export LC_ALL=C
n=$({ grep -v foo <big_file |
      tee /dev/fd/3 |
      dd of=big_file conv=notrunc; } 3>&1 | wc -c)
dd if=/dev/null of=big_file bs=1 seek=$n

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

grep -v foo <big_file | perl -e '
  close STDOUT;
  open STDOUT, "+<", $ARGV[0] or die;
  while (<STDIN>) {print}
  truncate STDOUT, tell STDOUT or die
' big_file

16

বোর্নের মতো শেল সহ:

{
  cat < bigfile | grep -v to-exclude
  perl -e 'truncate STDOUT, tell STDOUT'
} 1<> bigfile

কোনও কারণে, মনে হয় লোকে 40 বছরের পুরানো standard এবং স্ট্যান্ডার্ড রিড + রাইটিং রিডাইরেকশন অপারেটর সম্পর্কে ভুলে যাওয়ার ঝোঁক রয়েছে ।

আমরা খোলা bigfileপঠিত + + লেখার মোডে এবং (আসলে একটি সবচেয়ে এখানে) ছাড়াই ছাঁটাই stdoutযখন bigfileখোলা (আলাদাভাবে) হল catএর stdin। পরে grepবন্ধ হয়ে গেলে, এবং যদি এটি কিছু লাইন সরিয়ে ফেলেছে তবে stdoutএখন এটি কোথাও কোথাও নির্দেশ করে bigfile, আমাদের এই বিন্দুটি অতিক্রম করে কী কী তা থেকে মুক্তি পাওয়া দরকার। সুতরাং যে perlকমান্ডটি truncate STDOUTবর্তমান অবস্থানে ( tell STDOUT) হিসাবে ফাইল ( ) কে ছাঁটাই করে ।

(এটি জিএনইউর catজন্য grepযা অন্যথায় যদি স্টিন এবং স্টাডআউট একই ফাইলটিতে নির্দেশ করে তবে অভিযোগ করে)।


¹ ঠিক আছে, <>সত্তরের দশকের শেষের দিক থেকে বোর্ন শেল থেকে শুরু করে, এটি প্রাথমিকভাবে অ-দীক্ষিত এবং সঠিকভাবে প্রয়োগ করা হয়নি । এটা তোলে মূল বাস্তবায়ন ছিল না ash1989 থেকে এবং যখন এটি একটি POSIX হয় shফেরৎ অপারেটর (POSIX যেমন তাড়াতাড়ি 90s থেকে shভিত্তি করে উপর ksh88, এটা FreeBSD 'র ক্ষেত্রে যোগ হয়েছিল সবসময় এটা ছিল) sh2000 পর্যন্ত উদাহরণস্বরূপ, তাই portably 15 বছর পুরানো সম্ভবত আরও সঠিক। এছাড়াও মনে রাখবেন যে ডিফল্ট ফাইল বর্ণনাকারী নির্দিষ্ট <>না করে সমস্ত শেলগুলিতে থাকে তবে এর ksh93মধ্যে 2010 সালে ksh93t + তে 0 থেকে 1 তে পরিবর্তিত হয়েছে (পশ্চাদগম্য সামঞ্জস্যতা এবং POSIX সম্মতি ভঙ্গ করা)


2
আপনি কি ব্যাখ্যা করতে পারেন perl -e 'truncate STDOUT, tell STDOUT'? এটি অন্তর্ভুক্ত না করে আমার পক্ষে কাজ করে। পার্ল ব্যবহার না করে একই জিনিস অর্জনের কোনও উপায়?
অ্যারন ব্লেনকুশ

1
অ্যারোনব্লেনকুশ, সম্পাদনা দেখুন।
স্টাফেন চেজেলাস

1
একেবারে উজ্জ্বল - আপনাকে ধন্যবাদ। আমি তখন সেখানে ছিলাম, তবে এটি মনে রাখবেন না .... "36 বছর বয়সী" স্ট্যান্ডার্ডের জন্য একটি উল্লেখ মজাদার হবে, যেহেতু এটি এন.ইউইকিপিডিয়া . org / উইকি / বোর্ন_শেল- তে উল্লেখ নেই । এবং এটি কি জন্য ব্যবহার করা হয়েছিল? আমি সুনোস 5.6 এ একটি বাগ ফিক্সের একটি রেফারেন্স দেখতে পাচ্ছি: redirection "<>" fixed and documented (used in /etc/inittab f.i.). যা একটি ইঙ্গিত।
nealmcb

2
@ নিউম্যাকবি, সম্পাদনা দেখুন।
স্টাফেন চেজেলাস

@ স্টাফেনচাজেলা আপনার সমাধানটি এই উত্তরের সাথে কীভাবে তুলনা করে ? এটি দৃশ্যত একই জিনিসটি করে তবে দেখতে আরও সহজ।
akhan

9

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

বোর্ন শেল আপডেট করার জন্য একটি ফাইল খোলার সীমাবদ্ধ ইউটিলিটি। শেলটি আপনাকে কোনও ফাইল সন্ধানের জন্য এবং তার নতুন দৈর্ঘ্য নির্ধারণ করার কোনও উপায় দেয় না (যদি পুরানোটির চেয়ে ছোট হয়)। তবে এটি সহজে প্রতিকার করা যায়, তাই খুব সহজেই আমি অবাক হয়ে যাই এটি কোনও স্ট্যান্ডার্ড ইউটিলিটিগুলির মধ্যে নয় /usr/bin

এইটা কাজ করে:

$ grep -n foo T
8:foo
$ (exec 4<>T; grep foo T >&4 && ftruncate 4) && nl T; 
     1  foo

এটি যেমন করে (স্টাফেনের টুপি টিপ):

$ { grep foo T && ftruncate; } 1<>T  && nl T; 
     1  foo

(আমি জিএনইউ গ্রেপ ব্যবহার করছি he তার উত্তর লেখার পর থেকে সম্ভবত কিছু পরিবর্তন হয়েছে))

ব্যতীত, আপনার কাছে / usr / bin / ftruncate নেই । সি এর কয়েক ডজন লাইনের জন্য, আপনি নীচে দেখতে পারেন। এই ফ্রন্টসেট ইউটিলিটি স্ট্যান্ডার্ড আউটপুট এবং বর্তমান অবস্থানে ডিফল্ট করে একটি স্বেচ্ছাসেবী ফাইল বর্ণনাকারীকে একটি স্বেচ্ছাসেবী দৈর্ঘ্যে ছাঁটাই করে দেয়

উপরের কমান্ড (1 ম উদাহরণ)

  • Tআপডেটের জন্য ফাইল বর্ণনাকারী 4 চালু করে op ওপেন (2) এর মতোই, ফাইলটি খোলার ফলে বর্তমান অফসেটটি 0 তে অবস্থিত।
  • গ্রেপ এর পরে Tসাধারণত প্রক্রিয়া করা হয় এবং শেলটি তার আউটপুটটিকে Tবিবরণকারী 4 এর মাধ্যমে পুনঃনির্দেশ করে ।
  • ftruncate ftruncate (2) বর্ণনাকারী 4 এ কল করে, বর্তমান অফসেটের মানটির দৈর্ঘ্য নির্ধারণ করে (ঠিক যেখানে গ্রেপ এটি রেখেছিল)।

Subshell তারপর প্রস্থান করে, বর্ণনাকারী 4. বন্ধ এখানে ftruncate :

#include <err.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int
main( int argc, char *argv[] ) {
  off_t i, fd=1, len=0;
  off_t *addrs[2] = { &fd, &len };

  for( i=0; i < argc-1; i++ ) {
    if( sscanf(argv[i+1], "%lu", addrs[i]) < 1 ) {
      err(EXIT_FAILURE, "could not parse %s as number", argv[i+1]);
    }
  }

  if( argc < 3 && (len = lseek(fd, 0, SEEK_CUR)) == -1 ) {
    err(EXIT_FAILURE, "could not ftell fd %d as number", (int)fd);
  }


  if( 0 != ftruncate((int)fd, len) ) {
    err(EXIT_FAILURE, argc > 1? argv[1] : "stdout");
  }

  return EXIT_SUCCESS;
}

NB, ftruncate (2) এইভাবে ব্যবহার করার সময় ননপোর্টেবল। নিখুঁত সাধারণতার জন্য, সর্বশেষ লিখিত বাইটটি পড়ুন, ফাইলটি O_WRONLY আবার খুলুন, সন্ধান করুন, বাইটটি লিখুন এবং বন্ধ করুন।

এই প্রশ্নটি 5 বছরের পুরানো দেওয়া, আমি এই সমাধানটি প্রকাশ্য বলতে যাচ্ছি। এটি একটি নতুন বর্ণনাকারী এবং অপারেটর খোলার জন্য এক্সেকের সুবিধা নেয় <>যা উভয়ই আরকেন। আমি কোনও স্ট্যান্ডার্ড ইউটিলিটি ভাবতে পারি না যা ফাইল ডেস্ক্রিপ্টরের মাধ্যমে কোনও ইনডকে ম্যানিপুলেট করে। (বাক্য ftruncate >&4গঠনটি হতে পারে তবে আমি নিশ্চিত যে উন্নতি করছি না।) এটি ক্যামের দক্ষ, অনুসন্ধানী উত্তরের চেয়ে যথেষ্ট সংক্ষিপ্ত। এটি স্টাফেনের আইএমও থেকে একটু পরিষ্কার, যদি না আপনি পার্লকে আমার চেয়ে বেশি পছন্দ করেন। আমি আশা করি যে কেউ এটি দরকারী হবে।

একই জিনিসটি করার একটি ভিন্ন উপায় হ'ল lseek (2) এর একটি এক্সিকিউটেবল সংস্করণ যা বর্তমান অফসেটটি রিপোর্ট করে; আউটপুটটি / usr / bin / truncate ব্যবহার করা যেতে পারে , যা কিছু লিনাক্সির সরবরাহ করে।


5

ed জায়গাটিতে কোনও ফাইল সম্পাদনা করার জন্য সম্ভবত সঠিক পছন্দ:

ed my_big_file << END_OF_ED_COMMANDS
g/foo:/d
w
q 
END_OF_ED_COMMANDS

আমি ধারণাটি পছন্দ করি, তবে যতক্ষণ না বিভিন্ন edসংস্করণগুলি আলাদাভাবে আচরণ করে ..... এটি man ed(জিএনইউ এড 1.4) থেকে এসেছে ...If invoked with a file argument, then a copy of file is read into the editor's buffer. Changes are made to this copy and not directly to file itself.
পিটার.ও

@ ফ্রেড, আপনি যদি বোঝাচ্ছেন যে পরিবর্তনগুলি সংরক্ষণ করা নামযুক্ত ফাইলকে প্রভাবিত করবে না, আপনি ভুল। আমি এই উদ্ধৃতিটির ব্যাখ্যা করছি যে আপনি যতক্ষণ না সেগুলি সংরক্ষণ করেন আপনার পরিবর্তনগুলি প্রতিফলিত হয় না lected আমি বুঝতে পারি যে edফাইলটি বাফারে পড়ার পরে 35 জিবি ফাইল সম্পাদনা করার জন্য এটি কোনও সমাধান নয়।
গ্লেন জ্যাকম্যান 19

2
আমি ভাবছিলাম যে এর অর্থ সম্পূর্ণ ফাইলটি বাফারে লোড হবে .. তবে সম্ভবত এটির প্রয়োজনীয় অংশটি বাফারে লোড করা হয়েছে .. আমি কিছুক্ষণের জন্য এড সম্পর্কে আগ্রহী ছিলাম ... আমি ভেবেছিলাম ইনটু সিটু এডিটিং করতে পারত ... আমাকে কেবল একটি বড় ফাইল চেষ্টা করতে হবে ... এটি যদি কাজ করে তবে এটি একটি যুক্তিসঙ্গত সমাধান হয়, তবে আমি যেমন লিখছি, আমি ভাবতে শুরু করি যে এটি সেটাই হতে পারে যা অনুপ্রাণিত সেড ( বৃহত ডেটা খণ্ডগুলির সাথে কাজ করা থেকে মুক্তি পেয়েছি ... আমি লক্ষ্য করেছি যে 'এড' আসলে কোনও স্ক্রিপ্ট থেকে প্রবাহিত ইনপুট গ্রহণ করতে পারে (এর উপসর্গযুক্ত !), সুতরাং এটির হাতাটি আরও কয়েকটি আকর্ষণীয় কৌশল থাকতে পারে
পিটার.ও

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

5

আপনার ফাইলটি খোলার জন্য ব্যাশ রিড / রাইটিং ফাইল ডেসক্রিপটর ব্যবহার করতে পারেন (এটিকে সিউথিট করে ওভাররাইট করতে), sedএবং truncate... তবে অবশ্যই, আপনার পরিবর্তনগুলি এতদূর পড়া তথ্যের পরিমাণের চেয়ে বড় হতে দেবেন না ।

এখানে স্ক্রিপ্টটি রয়েছে (ব্যবহারসমূহ: ব্যাশ ভেরিয়েবল AS BASHPID)

# Create a test file
  echo "going abc"  >junk
  echo "going def" >>junk
  echo "# ORIGINAL file";cat junk |tee >( wc=($(wc)); echo "# ${wc[0]} lines, ${wc[2]} bytes" ;echo )
#
# Assign file to fd 3, and open it r/w
  exec 3<> junk  
#
# Choose a unique filename to hold the new file size  and the pid 
# of the semi-asynchrounous process to which 'tee' streams the new file..  
  [[ ! -d "/tmp/$USER" ]] && mkdir "/tmp/$USER" 
  f_pid_size="/tmp/$USER/pid_size.$(date '+%N')" # %N is a GNU extension: nanoseconds
  [[ -f "$f_pid_size" ]] && { echo "ERROR: Work file already exists: '$f_pid_size'" ;exit 1 ; }
#
# run 'sed' output to 'tee' ... 
#  to modify the file in-situ, and to count the bytes  
  <junk sed -e "s/going //" |tee >(echo -n "$BASHPID " >"$f_pid_size" ;wc -c >>"$f_pid_size") >&3
#
#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
# The byte-counting process is not a child-process, 
# so 'wait' doesn't work... but wait we must...  
  pid_size=($(cat "$f_pid_size")) ;pid=${pid_size[0]}  
  # $f_pid_size may initially contain only the pid... 
  # get the size when pid termination is assured
  while [[ "$pid" != "" ]] ; do
    if ! kill -0 "$pid" 2>/dev/null; then
       pid=""  # pid has terminated. get the byte count
       pid_size=($(cat "$f_pid_size")) ;size=${pid_size[1]}
    fi
  done
  rm "$f_pid_size"
#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
#
  exec 3>&- # close fd 3.
  newsize=$(cat newsize)
  echo "# MODIFIED file (before truncating)";cat junk |tee >( wc=($(wc)); echo "# ${wc[0]} lines, ${wc[2]} bytes" ;echo )  cat junk
#
 truncate -s $newsize junk
 echo "# NEW (truncated) file";cat junk |tee >( wc=($(wc)); echo "# ${wc[0]} lines, ${wc[2]} bytes" ;echo )  cat junk
#
exit

এখানে পরীক্ষা আউটপুট

# ORIGINAL file
going abc
going def
# 2 lines, 20 bytes

# MODIFIED file (before truncating)
abc
def
c
going def
# 4 lines, 20 bytes

# NEW (truncated) file
abc
def
# 2 lines, 8 bytes

3

আমি ফাইলটি মেমরি-মানচিত্র করব, নগ্ন স্মৃতিতে চর * পয়েন্টার ব্যবহার করে জায়গাগুলি সবকিছু করব, তারপরে ফাইলটি আনম্যাপ করুন এবং এটি কেটে দিন।


3
+1, তবে কেবলমাত্র 64৪-বিট সিপিইউ এবং ওএসের বিস্তৃত উপলব্ধতার কারণে এটি এখন 35 গিগাবাইট ফাইলের সাহায্যে সম্ভব করে তোলে। যারা এখনও 32-বিট সিস্টেমে আছেন (এমনকি এই সাইটের দর্শকের বিশাল সংখ্যাগরিষ্ঠরাও আমার সন্দেহ আছে) তারা এই সমাধানটি ব্যবহার করতে পারবেন না।
ওয়ারেন ইয়ং

2

হুবহু বাস্তবে নয় তবে - এটি একই পরিস্থিতিতে ব্যবহার হতে পারে।
যদি ডিস্কের জায়গার সমস্যা হয় তবে প্রথমে ফাইলটি সংকুচিত করুন (যেহেতু এটি পাঠ্য তাই এটি একটি বিশাল হ্রাস দেবে) তারপরে একটি সঙ্কোচিত / সংকোচন পাইপলাইনের মাঝখানে স্বাভাবিক উপায়ে সেড (বা গ্রেপ, বা যাই হোক না কেন) ব্যবহার করুন।

# Reduce size from ~35Gb to ~6Gb
$ gzip MyFile

# Edit file, creating another ~6Gb file
$ gzip -dc <MyFile.gz | sed -e '/foo/d' | gzip -c >MyEditedFile.gz

2
তবে অবশ্যই গিজিপ ডিস্কে সংক্ষেপিত সংস্করণটি সংকোচিত সংস্করণের সাথে প্রতিস্থাপনের আগে লিখছে, সুতরাং অন্যান্য বিকল্পগুলির মত নয়, আপনার কমপক্ষে সেই অতিরিক্ত স্থানের প্রয়োজন। তবে এটি নিরাপদ, যদি আপনি জায়গা পেয়ে থাকেন (যা আমি করি না ....)
nealmcb

এটি একটি চতুর সমাধান যা দুটির পরিবর্তে কেবল একটি সংক্ষেপণ সম্পাদন করতে আরও অনুকূলিত হতে পারে:sed -e '/foo/d' MyFile | gzip -c >MyEditedFile.gz && gzip -dc MyEditedFile.gz >MyFile
টড ওভেন

0

এই প্রশ্নটি গুগল করা যে কারও উপকারের জন্য, সঠিক উত্তরটি হ'ল অস্পষ্ট শেল বৈশিষ্ট্যগুলি অনুসন্ধান করা বন্ধ করুন যা আপনার ফাইলকে তুচ্ছ পারফরম্যান্স লাভের জন্য কলুষিত করার ঝুঁকিপূর্ণ এবং পরিবর্তে এই প্যাটার্নটির কিছু প্রকরণ ব্যবহার করুন:

grep "foo" file > file.new && mv file.new file

কেবলমাত্র অত্যন্ত অস্বাভাবিক পরিস্থিতিতে যে এটি কোনও কারণে সম্ভব নয়, আপনার এই পৃষ্ঠার অন্যান্য উত্তরগুলির মধ্যে গুরুত্ব সহকারে বিবেচনা করা উচিত (যদিও তারা পড়তে অবশ্যই আগ্রহী)। আমি স্বীকার করব যে দ্বিতীয় ফাইল তৈরির জন্য ডিস্কের জায়গা না থাকার ওপির ঝাঁকুনি ঠিক এমন একটি পরিস্থিতি। তারপরেও, অন্যান্য বিকল্পগুলি উপলভ্য রয়েছে, যেমন @ এড র‌্যান্ডাল এবং @ বেসিল স্টারিনকিভিচ provided


1
আমি ভুল বুঝতে পারি তবে ওপি মৌলিক যা বলেছিল তাতে কিছুই করার নেই। অস্থায়ী ফাইলের জন্য পর্যাপ্ত ডিস্কস্পেস ছাড়াই বিগফাইলে ওরফে ইনলাইন সম্পাদনা।
কিউই

@ কিউই এটি এই প্রশ্নের অন্যান্য দর্শকদের লক্ষ্য করে একটি উত্তর (যার মধ্যে এখনও পর্যন্ত প্রায় 15,000 হয়েছে)। প্রশ্ন "জায়গাটিতে কোনও ফাইল পরিবর্তন করার কোনও উপায় আছে কি?" ওপির নির্দিষ্ট ব্যবহারের ক্ষেত্রে বিস্তৃত প্রাসঙ্গিকতা রয়েছে।
টড ওভেন

-3

echo -e "$(grep pattern bigfile)" >bigfile


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