ডিলিমিটারের সঠিক সংখ্যা সম্বলিত কেবল রেখাগুলি রাখুন


9

আমার কাছে 10 টি ক্ষেত্র কমা দ্বারা পৃথক করে একটি বিশাল সিএসভি ফাইল রয়েছে। দুর্ভাগ্যক্রমে, কিছু লাইনগুলি ত্রুটিযুক্ত এবং ঠিক 10 টি কমা অন্তর্ভুক্ত নয় (যখন আমি আর-তে ফাইলটি পড়তে চাইছি তখন কিছু সমস্যা দেখা দেয়)। আমি কীভাবে কেবলমাত্র 10 টি কমা থাকা লাইনগুলি ফিল্টার করব?


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

1
আসলে পুরো বিষয়টা বিস্তারিত বিবেচনা খুঁজছেন, প্রশ্নকর্তা সেখানে নেই চান আর বা কম ম্যাচ। এই প্রশ্নের একটি নতুন শিরোনাম প্রয়োজন। তবে grepউত্তর কোনও প্রশ্নেরই গ্রহণযোগ্য উত্তর নেই ...
মাইক্রজারভ

উত্তর:


21

অন্য একটি পসিক্স:

awk -F , 'NF == 11' <file

যদি লাইনে 10 টি কমা থাকে তবে এই লাইনে 11 টি ক্ষেত্র থাকবে। সুতরাং আমরা কেবল ক্ষেত্রের সীমানা হিসাবে awkব্যবহার করি ,। যদি ক্ষেত্রের সংখ্যা 11 হয়, শর্তটি NF == 11সত্য হয়, awkতবে ডিফল্ট ক্রিয়াটি সম্পাদন করে print $0


5
এই প্রশ্নটি আসলে আমার মনে এটাই প্রথম ছিল mind আমি ভেবেছিলাম এটি ওভারকিল, তবে কোডটির দিকে তাকিয়ে ... এটি অবশ্যই পরিষ্কার। অন্যের সুবিধার জন্য: -Fক্ষেত্র বিভাজক নির্ধারণ করে এবং NFপ্রদত্ত লাইনে ক্ষেত্রের সংখ্যা উল্লেখ করে। যেহেতু কোনও কোড ব্লক {statement}শর্তে যুক্ত করা হয়নি NF == 11, তাই ডিফল্ট ক্রিয়াটি লাইনটি প্রিন্ট করা। (@ কুওগলম, যদি আপনি চান তবে এই ব্যাখ্যাটি সংযোজন করতে দ্বিধা বোধ করবেন।)
ওয়াইল্ডকার্ড

4
+1: খুব মার্জিত এবং পঠনযোগ্য সমাধান যা খুব সাধারণ। আমি উদাহরণস্বরূপ সমস্ত ত্রুটিযুক্ত রেখাগুলি খুঁজে পেতে পারিawk -F , 'NF != 11' <file
মিরোস্লাভ সাবো

@ গার্ডেনহেড: ওপি তার মন্তব্যে বলেছিল যেহেতু এটি পাওয়া সহজ। আমি আমার মোবাইল থেকে কিছু সময় উত্তর দিচ্ছি, সুতরাং বিশদ বিবরণ যুক্ত করা কঠিন।
cuonglm

1
@ মিকসার্ভ: না, দুঃখিত যদি আমি আপনাকে বিভ্রান্ত করে তুলি তবে এটি কেবল আমার খারাপ ইংরেজি। আপনার 1-9 কমা দিয়ে 11 টি ক্ষেত্র থাকতে পারে না।
cuonglm

1
@ অলিভিয়ারডুলাক: এটি ফাইল শুরু করা -বা নামকরণ করা থেকে রক্ষা করে -
cuonglm

8

ব্যবহার egrep(বা grep -Eপসিক্সে):

egrep "^([^,]*,){10}[^,]*$" file.csv

এটি 10 ​​টি কমাযুক্ত কোনও কিছুই ফিল্টার করে: এটি সম্পূর্ণ রেখাগুলির সাথে ( ^শুরুতে এবং $শেষে) মেলে , {10}সিকোয়েন্সের ঠিক দশটি পুনরাবৃত্তি ( ) যোগ করে '', 'ব্যতীত কোনও অক্ষরের সংখ্যার পরে,' একক ',' " ( ([^,]*,)), ',' ( [^,]*) বাদে আবার যেকোন সংখ্যক অক্ষর অনুসরণ করে ।

-xঅ্যাঙ্কারগুলি ফেলে দেওয়ার জন্য আপনি প্যারামিটারটি ব্যবহার করতে পারেন :

grep -xE "([^,]*,){10}[^,]*" file.csv

এই কম কার্যকরী cuonglm এর awkসমাধান যদিও; পরবর্তীটি প্রায় 10 টি কমা সহ লাইনের জন্য আমার সিস্টেমে সাধারণত ছয়গুণ দ্রুত হয়। দীর্ঘতর লাইনগুলি বিশাল ধীরগতির কারণ হবে।


5

সবচেয়ে সহজ grepকোড যা কাজ করবে:

grep -xE '([^,]*,){10}[^,]*'

ব্যাখ্যা:

-xনিশ্চিত করে যে প্যাটার্নটি অবশ্যই কেবল তার কিছু অংশের চেয়ে পুরো লাইনের সাথে মেলে । এটি গুরুত্বপূর্ণ কারণ আপনি 10 টিরও বেশি কমা দিয়ে লাইন মেলে না।

-E এর অর্থ "বর্ধিত রেজেক্স", যা আপনার রেজেক্সে কম ব্যাকস্ল্যাশ-পলায়নের জন্য তোলে।

প্যারেন্টেসিসগুলি গ্রুপিংয়ের জন্য ব্যবহৃত হয় এবং {10}তারপরে অর্থ প্যারেন্টেসিসের মধ্যে প্যাটার্নের এক সারিতে ঠিক দশটি ম্যাচ থাকতে হবে।

[^,]একটি অক্ষর শ্রেণি instance উদাহরণস্বরূপ, [c-f]যে কোনও একক অক্ষরের সাথে মিলবে যা ক c, ক d, ক eবা একটি f, এবং [^A-Z]কোনও একক অক্ষরের সাথে মিলবে যা বড় হাতের অক্ষর নয়। তাই [^,]কমা ব্যতীত যে কোনও একটি চরিত্রের সাথে মেলে।

*চরিত্র শ্রেণী মানে পরে "শূন্য বা এই আরও।"

সুতরাং রেজেক্স অংশটির ([^,]*,)অর্থ "কমা ব্যতীত যে কোনও চরিত্র যেকোন সংখ্যক বার (শূন্যগুণ সহ), তার পরে কমা" এবং এর মধ্যে {10}10 টি নির্দিষ্ট করে। তারপরে [^,]*বাকী নন-কমা অক্ষরের সাথে লাইনের শেষের সাথে মেলে।


5
sed -ne's/,//11;t' -e's/,/&/10p' <in >out

এটি প্রথমে 11 বা ততোধিক কমা দিয়ে যে কোনও লাইন শাখা করে এবং তারপরে 10 টি কমাতে মেলে কেবল তারাই প্রিন্ট করে।

স্পষ্টতই আমি এর আগে এর জবাব দিয়েছি ... কিছু প্যাটার্নের ঠিক 4 টি ঘটনা সন্ধান করে এমন একটি প্রশ্ন থেকে এখানে আমার লেখা চুরি হয়েছে:

আপনি কেবলমাত্র কমান্ডটিতে যুক্ত করে [num]একটি s///অবহেলা কমান্ডের সাহায্যে কোনও প্যাটার্নের উপস্থিতিকে লক্ষ্য করতে পারেন [num]। আপনি যখন tকোনও সফল প্রতিস্থাপনের জন্য থাকেন এবং কোনও লক্ষ্য :লেবেল নির্দিষ্ট না tকরেন, তখন স্ক্রিপ্টের বাইরে এস্ট শাখা থাকে। এর অর্থ আপনাকে যা করতে হবে তা হ'ল পরীক্ষা s///5বা আরও কমাগুলির জন্য পরীক্ষা করা , তারপরে যা অবশিষ্ট রয়েছে তা মুদ্রণ করুন।

অথবা, কমপক্ষে, লাইনগুলি পরিচালনা করে যা আপনার সর্বোচ্চ ৪ ছাড়িয়ে যায় App দৃশ্যত আপনার ন্যূনতম প্রয়োজনও রয়েছে। ভাগ্যক্রমে, এটি ঠিক যেমন সহজ:

sed -ne 's|,||5;t' -e 's||,|4p'

... শুধু 4 ঠা সংঘটন প্রতিস্থাপন ,নিজেই সঙ্গে একটি লাইন এবং আপনার কর্মপ্রণালী pউপর দ্রণ s///ubstitution পতাকা। ,5 বা ততোধিক বারের সাথে মেলে যে কোনও লাইন ইতিমধ্যে ছাঁটাই হয়েছে, 4 ,টি ম্যাচযুক্ত লাইনগুলিতে কেবল 4 টি রয়েছে ।


1
@ কুওগলম - প্রথমে আমার কাছে আসলে এটি ছিল, তবে লোকেরা আমাকে সবসময় বলছে যে আমার আরও পাঠযোগ্য কোড লিখতে হবে। যেহেতু আমি অন্যদের বিতর্কিত স্টাফগুলি পড়তে পারি না সেগুলি পড়তে পারি না আমি কী রাখব এবং কী ড্রপ করব তা নিশ্চিত নই ...? সুতরাং আমি দ্বিতীয় কমা রাখা।
মাইক্রজারভ

@ কুওগলম - আপনি আমাকে বিদ্রূপ করতে পারেন - এটি আমার অনুভূতিতে আঘাত করবে না। আমি একটা রসিকতা নিতে পারি আপনি যদি আমাকে উপহাস করছিলেন তবে এটি কিছুটা মজার ছিল। ঠিক আছে - আমি ঠিক নিশ্চিত ছিলাম না এবং জানতে চেয়েছিলাম। আমার মতে লোকেরা নিজেরাই হাসতে পারা উচিত। যাইহোক, আমি এখনও এটি না!
মাইক্রজারভ

হাহা, ঠিক আছে, এটি একটি খুব ইতিবাচক চিন্তাভাবনা। যাইহোক, আপনার সাথে চ্যাট করা খুব মজার এবং কখনও কখনও আপনি আমার মস্তিষ্ককে চাপ দিন।
cuonglm

এটি আকর্ষণীয় যে এই উত্তরে আমি যদি এটির s/hello/world/2সাথে প্রতিস্থাপন করি তবে s//world/2জিএনইউ সিড ভাল কাজ করে। sedউত্তরাধিকারী থেকে দু'জনের সাথে , /usr/5bin/posix/sedসেগফল্ট বাড়াতে, /usr/5bin/sedইনফিনিটিভ লুপে যায়।
cuonglm

@ মিক্সোসার্ভ, সম্পর্কে sedএবংawk (মন্তব্যে) আমাদের পূর্বের আলোচনার প্রসঙ্গে - আমি এই উত্তরটি পছন্দ করেছি এবং এটিকে উন্নত করে দিয়েছি তবে স্বীকৃত awkউত্তরের অনুবাদটি লক্ষ্য করুন : "11 টি ক্ষেত্র সহ লাইনগুলি মুদ্রণ করুন" এবং এই sedউত্তরের অনুবাদটি হ'ল: " ১১ তম কমা অপসারণের চেষ্টা; আপনি ব্যর্থ হলে পরের লাইনে যান। awkউত্তর কম্পিউটারে নির্দেশাবলী ঠিক ভাবে আপনি তাদের ইংরেজিতে প্রকাশ হবে দেয়। ( awkফিল্ড ভিত্তিক ডেটা জন্য ভাল।)
ওয়াইল্ডকার্ড

4

কিছু সংক্ষিপ্ত নিক্ষেপ python:

#!/usr/bin/env python2
with open('file.csv') as f:
    print '\n'.join(line for line in f if line.count(',') == 10)

এটি প্রতিটি লাইনটি পড়বে এবং লাইনে কমা সংখ্যাটি 10 ​​এর সমান line.count(',') == 10কিনা তা পরীক্ষা করবে, যদি প্রিন্ট করা হয় তবে এটি লাইন হবে।


2

এবং এখানে একটি পার্ল উপায়:

perl -F, -ane 'print if $#F==10'

-nকারণ perlস্ক্রিপ্ট দেওয়া লাইন দ্বারা তার ইনপুট ফাইল লাইন পড়া এবং চালানো -eপ্রতিটি লাইনে। -aস্বয়ংক্রিয় বিভাজন সক্রিয় করা হয়: প্রতিটি ইনপুট লাইন কর্তৃক প্রদত্ত মূল্যের ওপর বিভক্ত করা হবে -F(এখানে, একটি কমা) এবং অ্যারে হিসাবে সংরক্ষিত @F

$#F(অথবা, আরো সাধারণভাবে $#array), অ্যারের সর্বোচ্চ সূচক @F। যেহেতু অ্যারে শুরু হয় 0, 11 টি ক্ষেত্রের সাথে একটি লাইনে একটি @Fথাকবে 10। স্ক্রিপ্ট, সুতরাং 11 টি ক্ষেত্র থাকলে লাইনটি মুদ্রণ করে।


আপনি print if @F==11স্কেলার প্রসঙ্গে একটি অ্যারে হিসাবে উপাদানগুলির সংখ্যা ফেরান হিসাবেও করতে পারেন ।
সোবারিক

1

যদি ক্ষেত্রগুলিতে কমা বা নিউলাইন থাকতে পারে তবে আপনার কোডটি সিএসভি বুঝতে হবে । উদাহরণ (তিনটি কলাম সহ):

$ cat filter.csv
a,b,c
d,"e,f",g
1,2,3,4
one,two,"three
...continued"

$ cat filter.csv | python3 -c 'import sys, csv
> csv.writer(sys.stdout).writerows(
> row for row in csv.reader(sys.stdin) if len(row) == 3)
> '
a,b,c
d,"e,f",g
one,two,"three
...continued"

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

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