6 টির চেয়ে কম অক্ষরের একটি ফাইলের সমস্ত লাইন আমি কীভাবে সরিয়ে ফেলব?


17

আমার কাছে প্রায় 10 মিলিয়ন লাইনযুক্ত একটি ফাইল রয়েছে।

আমি এই ফাইলের সমস্ত লাইন ছয় অক্ষরের চেয়ে কম মুছে ফেলতে চাই।

আমি এটা কিভাবে করবো?


এই প্রশ্নটি কি স্ট্যাকওভারফ্লোয়ের জন্য আরও উপযুক্ত নয়?
ব্যবহারকারী 1073075

2
@ user1073075 এটি এখানে পুরোপুরি টপিকের।
শেঠ

উত্তর:


30

এটি করার অনেকগুলি উপায় রয়েছে।

ব্যবহার grep:

grep -E '^.{6,}$' file.txt >out.txt

এখন out.txtছয় বা তার বেশি অক্ষরের লাইন থাকবে।

বিপরীত উপায়:

grep -vE '^.{,5}$' file.txt >out.txt

sed5 বা তার কম দৈর্ঘ্যের লাইনগুলি ব্যবহার করে :

sed -r '/^.{,5}$/d' file.txt

বিপরীত উপায়, ছয় বা তার বেশি দৈর্ঘ্যের মুদ্রণ লাইন:

sed -nr '/^.{6,}$/p' file.txt 

>অপারেটর ব্যবহার করে আপনি আলাদা ফাইলে আউটপুট সংরক্ষণ করতে পারেন grepঅথবা -iবিকল্পগুলির বিকল্প ব্যবহার করে স্থানের মধ্যে ফাইলটি সম্পাদনা করতে পারেন sed:

sed -ri.bak '/^.{6,}$/' file.txt 

আসল ফাইলটিকে ব্যাক আপ করা হবে file.txt.bakএবং পরিবর্তিত ফাইলটি হবে file.txt

আপনি যদি ব্যাকআপ রাখতে চান না:

sed -ri '/^.{6,}$/' file.txt

শেল, স্লোয়ার ব্যবহার করে এটি করবেন না , এটি কেবল অন্য পদ্ধতিটি দেখানোর জন্যই:

while IFS= read -r line; do [ "${#line}" -ge 6 ] && echo "$line"; done <file.txt

ব্যবহার python, এমনকি ধীর চেয়ে grep, sed:

#!/usr/bin/env python2
with open('file.txt') as f:
    for line in f:
        if len(line.rstrip('\n')) >= 6:
            print line.rstrip('\n')

আরও পাইথোনিক হওয়ার জন্য আরও ভাল ব্যবহারের তালিকা বোধগম্যতা:

#!/usr/bin/env python2
with open('file.txt') as f:
     strip = str.rstrip
     print '\n'.join([line for line in f if len(strip(line, '\n')) >= 6]).rstrip('\n')

হ্যাঁ! আমি অজগর উত্তরটির জন্য প্রত্যাশী ছিলাম =)
টেলমেউ কেন

@ ডেভ্রোবোট আমি দেখি..তখন তালিকা সংজ্ঞাটি আমি যোগ করেছিলাম, আরও পাইথোনিক হোন ..
হিমাইল

1
এছাড়াও প্রথম ডেভেলটি ব্যবহার করার পরে @ ডেভরবোট নিশ্চিত হন না যে বিশাল ফাইলগুলিতে অজগরটি ধীর গতির। আসলে আমি নিশ্চিত যে পাইথন লক্ষ লক্ষ লাইনে দ্রুত, যেহেতু এটি প্রতি লাইনে পড়ে reads
জ্যাকব Vlijm

1
দ্বিতীয় অজগর উদাহরণটি জোড় করার আগে পুরো ফাইলটিকে মেমরির মধ্যে পড়ে। আমি মনে করি প্রথম অজগর উদাহরণটি এই উদাহরণে আরও ভাল।
ফাঁকা

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

19

এটা খুবই সাধারণ:

grep ...... inputfile > resultfile   #There are 6 dots

এই অত্যন্ত কার্যকরী, যেমন grepচেয়ে দরকার আরো বিশ্লেষণ করতে চেষ্টা করবে না, কিংবা অন্য কোন উপায়ে অক্ষর ব্যাখ্যা করা: এটা শুধু stdout- এ একটি (পুরো) লাইন (যা শেল তারপর resultfile রিডাইরেক্ট) পাঠাতে যত তাড়াতাড়ি 6 দেখেছি এই রেখায় .অক্ষরগুলি ( একটি রেজিপেক্স প্রসঙ্গে কোনও 1 টি অক্ষরের সাথে মেলে)।

সুতরাং গ্রেপ শুধুমাত্র আউটপুট লাইনগুলিতে 6 (বা আরও বেশি) অক্ষর রাখে এবং অন্যগুলি গ্রেপ দ্বারা আউটপুট হয় না যাতে তারা ফলাফলটি ফাইল করে না।


14

সমাধান # 1: সি ব্যবহার করে

দ্রুততম উপায়: এই সি প্রোগ্রামটি সংকলন এবং চালনা করুন:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_BUFFER_SIZE 1000000

int main(int argc, char *argv[]) {
    int length;

    if(argc == 3)
        length = atoi(argv[2]);
    else
        return 1;

    FILE *file = fopen(argv[1], "r");

    if(file != NULL) {
        char line[MAX_BUFFER_SIZE];

        while(fgets(line, sizeof line, file) != NULL) {
            char *pos;

            if((pos = strchr(line, '\n')) != NULL)
                *pos = '\0';
            if(strlen(line) >= length)
                printf("%s\n", line);
        }

        fclose(file);
    }
    else {
        perror(argv[1]);
        return 1;
    }

    return 0;
}

সংকলন করুন, দিয়ে gcc program.c -o programচালান ./program file line_length(যেখানে file= ফাইলের পথে = এবং line_lengthন্যূনতম লাইন দৈর্ঘ্য, আপনার ক্ষেত্রে 6; সর্বাধিক লাইন দৈর্ঘ্য 1000000প্রতি লাইন অক্ষরে সীমাবদ্ধ ; আপনি এর মান পরিবর্তন করে এটি পরিবর্তন করতে পারবেন MAX_BUFFER_SIZE)।

(বিকল্প করার জন্য কৌশল \nসঙ্গে \0পাওয়া এখানে ।)

শেল সমাধান ব্যতীত এই প্রশ্নের প্রস্তাবিত অন্যান্য সমস্ত সমাধানের সাথে তুলনা (8 টি অক্ষরের গড় দৈর্ঘ্য 10M লাইন সহ ~ 91MB ফাইলে পরীক্ষা করা):

time ./foo file 6

real    0m1.592s
user    0m0.712s
sys 0m0.160s

time grep ...... file

real    0m1.945s
user    0m0.912s
sys 0m0.176s

time grep -E '^.{6,}$'

real    0m2.178s
user    0m1.124s
sys 0m0.152s

time awk 'length>=6' file

real    0m2.261s
user    0m1.228s
sys 0m0.160s

time perl -lne 'length>=6&&print' file

real    0m4.252s
user    0m3.220s
sys 0m0.164s

sed -r '/^.{,5}$/d' file >out

real    0m7.947s
user    0m7.064s
sys 0m0.120s

./script.py >out
real    0m8.154s
user    0m7.184s
sys 0m0.164s

সমাধান # 2: এডাব্লুকে ব্যবহার করে:

awk 'length>=6' file
  • length>=6: যদি length>=6সত্য ফেরত দেয়, বর্তমান রেকর্ডটি মুদ্রণ করে।

সমাধান # 3: পার্ল ব্যবহার করে:

perl -lne 'length>=6&&print' file
  • যদি lenght>=6সত্য ফেরত দেয়, বর্তমান রেকর্ডটি মুদ্রণ করে।

% cat file
a
bb
ccc
dddd
eeeee
ffffff
ggggggg
% ./foo file 6
ffffff
ggggggg
% awk 'length>=6' file   
ffffff
ggggggg
% perl -lne 'length>=6&&print' file
ffffff
ggggggg

1
বিশ্বাস করুন..আমি আপনার awk সমাধানের জন্য অপেক্ষা করছিলাম ..
27:38 এ হিমাইল

2
@himayl এবং আমি অবিলম্বে প্রশ্নটি দেখতে পাইনি, তাই আমি জানতাম যে আপনি যদি অনলাইনে হয়ে থাকেন তবে আপনি আরও দ্রুত you আমার sedসমাধানটি মুছতে হয়েছিল (এটি ঘটে, আমি জানি)। এক্সডি
কোস

posচলকের বিন্দুটি কী ? আমি এটি lineএকটি নতুন লাইন চরিত্রের সাথে চরিত্রটিতে একটি পয়েন্টার ফিরিয়ে দিই , তবে আপনি কখনও এটি ব্যবহার করবেন বলে মনে হয় না। এবং যদি আপনি এটি না পান তবে আপনি এটির সমান সেট করেছেন \0
ব্যবহারকারী 1717828

@ ব্যবহারকারী 1717828 যদি আমি এটি খুঁজে পাই তবে আমি এটির সাথে প্রতিস্থাপন করব \0( strchr()চরিত্রটি না পাওয়া গেলে একটি NULL পয়েন্টার প্রদান করে )। বিন্দুটি প্রতিটি লাইনের শেষে প্রতিটি নিউলাইনকে প্রতিস্থাপন করে \0যাতে নতুন লাইনটি কখনই গণনা করা হয় না strlen(): এটি এমন যাতে শেষ লাইনে কোনও সম্ভাব্য অনুপস্থিত নিউলাইন নির্বিশেষে দৈর্ঘ্যটি সর্বদা 6 টির সাথে তুলনা করা যায়। আমি জানি যে শুধুমাত্র শেষ লাইনের সাথে আলাদাভাবে চিকিত্সা করা আরও কার্যকর হবে I আমি সম্ভবত এটি পরে আপডেট করব।
kos

1
@ ট্রিপলি ধারণাটি ছিল এককালীন চাকরির চেয়ে বেশি কিছু বা আরও বড় ফাইলের জন্য কার্যকর সমাধান যুক্ত করা , তবে : আমি grepএকই ফাইলটিতে সমাধানটি পরীক্ষা করেছি এবং এটি আসলে দ্রুত (সম্ভবত কারণ strlen()এখানে সেরা ধারণা নয়) । getchar()পরিবর্তে প্রথম এন অক্ষরটি পরীক্ষা করার জন্য আমি একটি লুপ ব্যবহার করার চেষ্টা করব , আমার ধারণা এটি দৃশ্যমানভাবে উন্নত করা উচিত। এবং হ্যাঁ, বাফারের দৈর্ঘ্যের উপরের কোনও লাইন কেবল বাফারের দৈর্ঘ্যে কাটা হয়।
kos

2

আপনি প্রাক্তন মোডে ভিম ব্যবহার করতে পারেন:

ex -sc 'v/\v.{6}/d' -cx file
  1. \v যাদু চালু করুন

  2. .{6} 6 বা ততোধিক অক্ষরের সাথে লাইনগুলি সন্ধান করুন

  3. v ব্যুত্ক্রমে নির্বাচন

  4. d মুছে ফেলা

  5. x সংরক্ষণ করেন এবং বন্ধ করেন


1

রুবি দ্রবণ:

$ cat input.txt                                                                                                          
abcdef
abc
abcdefghijk

$ ruby -ne 'puts $_ if $_.chomp.length() >= 6 ' < input.txt                                                              
abcdef
abcdefghijk

সহজ ধারণা: রুবির স্টিডিনে ফাইলটি পুনর্নির্দেশ করুন এবং স্ট্ডিন থেকে প্রিন্ট লাইন কেবল তার দৈর্ঘ্য বড় বা 6 এর সমান হলে

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