কলাম দ্বারা 'ইউনিট' করার কোনও উপায় আছে?


195

আমার কাছে একটি .csv ফাইল রয়েছে:

stack2@example.com,2009-11-27 01:05:47.893000000,example.net,127.0.0.1
overflow@example.com,2009-11-27 00:58:29.793000000,example.net,255.255.255.0
overflow@example.com,2009-11-27 00:58:29.646465785,example.net,256.255.255.0
...

আমাকে ফাইল থেকে সদৃশ ই-মেইলগুলি (পুরো লাইন) সরিয়ে ফেলতে হবে ( overflow@example.comউদাহরণস্বরূপ উপরের উদাহরণে থাকা লাইনগুলির মধ্যে একটি)। আমি uniqকেবলমাত্র 1 ফিল্ডে (কমা দ্বারা পৃথক) কীভাবে ব্যবহার করব ? মতে man, uniqকলামগুলির জন্য বিকল্প নেই।

আমি কিছু দিয়ে চেষ্টা করেছি sort | uniqকিন্তু কাজ করে না।

উত্তর:


325
sort -u -t, -k1,1 file
  • -u অনন্য জন্য
  • -t, সুতরাং কমা হ'ল সীমানা
  • -k1,1 মূল ক্ষেত্রের জন্য 1

পরীক্ষার ফলাফল:

overflow@domain2.com,2009-11-27 00:58:29.793000000,xx3.net,255.255.255.0 
stack2@domain.com,2009-11-27 01:05:47.893000000,xx2.net,127.0.0.1 

3
কলামটিতে নিজেই কমা রয়েছে (উদ্ধৃতি সহ)
user775187

13
কেন আপনার 1 -1 -1 এর দরকার? শুধু-কে 1 কেন নয়?
হ্যালো_এখানে_আর

18
@hello_there_andy: ম্যানুয়ালটিতে এটি ব্যাখ্যা করা হয়েছে ( man sort)। এটি স্টার্ট এবং স্টপ অবস্থানের জন্য দাঁড়িয়েছে।
সেরানানো

3
@CarlSmotricz: আমি এটা পরীক্ষিত এবং এটি নিশ্চিত কি sort'র র manpage বলছে: " -u, --unique সঙ্গে -c, কঠোর ক্রম জন্য চেক; ছাড়া -c, আউটপুট একটি সমান রানের শুধুমাত্র প্রথম ।" সুতরাং, এটি সত্যই "বাছাইয়ের আগে সদৃশটির প্রথম ঘটনা।"
জেরেমিয়া

2
এই পাশাপাশি লাইন ক্রম পরিবর্তন করে, তাই না?
rkachach

102
awk -F"," '!_[$1]++' file
  • -F ক্ষেত্র বিভাজক সেট করে।
  • $1 প্রথম ক্ষেত্র।
  • _[val]valহ্যাশ _(একটি নিয়মিত ভেরিয়েবল) এ দেখায় ।
  • ++ বৃদ্ধি, এবং পুরানো মান প্রদান।
  • ! যৌক্তিক নয়।
  • শেষে একটি অন্তর্নিহিত মুদ্রণ আছে।

4
এই পদ্ধতির বাছাইয়ের চেয়ে
দ্বিগুণ

9
মূল ক্রমে লাইনগুলি রাখার এটিও অতিরিক্ত সুবিধা!
সমৃদ্ধ ওয়াল

8
আপনার যদি প্রথমটির পরিবর্তে শেষ ইউনিকের প্রয়োজন হয় তবে এই অজস্ক্র স্ক্রিপ্টটি সহায়তা করবে:awk -F',' '{ x[$1]=$0 } END { for (i in x) print x[i] }' file
সুকিমা

3
@েশ্বর কেবল অভিধান সূচকে আরও ক্ষেত্র যুক্ত করুন! উদাহরণস্বরূপ, !_[$1][$2]++প্রথম দুটি ক্ষেত্র অনুসারে বাছাই করতে ব্যবহার করা যেতে পারে। awkযদিও আমার -ফু তেমন শক্তিশালী নয় যে ক্ষেত্রে বিভিন্ন ক্ষেত্রে অনন্য হয়ে উঠতে সক্ষম। :(
সোহম চৌধুরী

1
উজ্জ্বল! এই বিকল্পটি উত্তরের চেয়ে ভাল কারণ এটি লাইনগুলিকে অর্ডার করে
rkachach

16

একাধিক কলাম বিবেচনা করা।

1 এবং কলাম 3 কলামের উপর ভিত্তি করে অনন্য তালিকাটিকে বাছাই করুন এবং দিন:

sort -u -t : -k 1,1 -k 3,3 test.txt
  • -t : কোলন বিভাজক হয়
  • -k 1,1 -k 3,3 কলাম 1 এবং 3 কলাম ভিত্তিক

8

অথবা আপনি যদি ইউনিক ব্যবহার করতে চান:

<mycvs.cvs tr -s ',' ' ' | awk '{print $3" "$2" "$1}' | uniq -c -f2

দেয়:

1 01:05:47.893000000 2009-11-27 tack2@domain.com
2 00:58:29.793000000 2009-11-27 overflow@domain2.com
1

5
আমি একটি সম্ভাব্য সরলকরণটি উল্লেখ করতে চাই: আপনি এটিকে ফেলে দিতে পারেন cat! ট্রায় পাইপিংয়ের পরিবর্তে, ট্রাম ব্যবহার করে ফাইলটি পড়ুন <। পাইপিং catকরা একটি সাধারণ অযৌক্তিক জটিলতা যা নবাগতদের দ্বারা ব্যবহৃত হয়। প্রচুর পরিমাণে ডেটার জন্য একটি পারফরম্যান্স প্রভাব থাকতে হবে।
কার্ল স্মট্রিক্জ

4
জানা ভাল. ধন্যবাদ! (অবশ্যই এটি "বিড়াল" এবং "অলসতা" চিন্তাভাবনা করে তোলে;))
কার্স্টেন সি

ক্ষেত্রগুলির বিপরীতকরণগুলি সহজ করা যায় rev
হিল্কে ওালিঙ্গা

5

আপনি যদি সর্বশেষ ডুপ্লিকেটগুলি ব্যবহার করতে পারেন তবে এটি ধরে রাখতে চান

 tac a.csv | sort -u -t, -r -k1,1 |tac

যা আমার প্রয়োজন ছিল

এখানে

tac লাইন দ্বারা ফাইল লাইন বিপরীত হবে


1

এখানে একটি খুব নিফটি উপায়।

স্বতন্ত্রতার জন্য তুলনা করার জন্য কলামটি একটি নির্দিষ্ট প্রস্থ হিসাবে প্রথমে সামগ্রীটি বিন্যাস করুন। এটি করার একটি উপায় হ'ল ক্ষেত্র / কলামের প্রস্থ নির্দিষ্টকরণকারক ("% 15s") সহ উইন্ডো প্রিন্টফ ব্যবহার করা।

ইউনিকের -f এবং -w বিকল্পগুলি পূর্ববর্তী ক্ষেত্রগুলি / কলামগুলি এড়াতে এবং তুলনার প্রস্থ (কলাম (গুলি) প্রস্থ) নির্দিষ্ট করতে ব্যবহৃত হতে পারে।

এখানে তিনটি উদাহরণ দেওয়া হল।

প্রথম উদাহরণে ...

1) অস্থায়ীভাবে আগ্রহের কলামটি ক্ষেত্রের সর্বাধিক প্রস্থের চেয়ে বড় বা সমান একটি নির্দিষ্ট প্রস্থকে তৈরি করুন।

2) পূর্ববর্তী কলামগুলি এড়াতে -f ইউনিক বিকল্পটি ব্যবহার করুন, এবং প্রস্থটি tmp_fixed_width এ সীমাবদ্ধ করতে -w ইউনিট বিকল্পটি ব্যবহার করুন।

3) এর প্রস্থটি "পুনরুদ্ধার" করতে কলাম থেকে পিছনের জায়গাগুলি সরান (ধরে নেওয়া যাক আগে কোনও পিছনে স্থান নেই)।

printf "%s" "$str" \
| awk '{ tmp_fixed_width=15; uniq_col=8; w=tmp_fixed_width-length($uniq_col); for (i=0;i<w;i++) { $uniq_col=$uniq_col" "}; printf "%s\n", $0 }' \
| uniq -f 7 -w 15 \
| awk '{ uniq_col=8; gsub(/ */, "", $uniq_col); printf "%s\n", $0 }'

দ্বিতীয় উদাহরণে ...

একটি নতুন ইউনিক কলাম 1 তৈরি করুন। তারপরে ইউনিক ফিল্টার প্রয়োগ করার পরে এটি সরিয়ে দিন।

printf "%s" "$str" \
| awk '{ uniq_col_1=4; printf "%15s %s\n", uniq_col_1, $0 }' \
| uniq -f 0 -w 15 \
| awk '{ $1=""; gsub(/^ */, "", $0); printf "%s\n", $0 }'

তৃতীয় উদাহরণটি দ্বিতীয়টির মতো, তবে একাধিক কলামের জন্য।

printf "%s" "$str" \
| awk '{ uniq_col_1=4; uniq_col_2=8; printf "%5s %15s %s\n", uniq_col_1, uniq_col_2, $0 }' \
| uniq -f 0 -w 5 \
| uniq -f 1 -w 15 \
| awk '{ $1=$2=""; gsub(/^ */, "", $0); printf "%s\n", $0 }'

-3

ভাল, কলামটি awk সহ বিচ্ছিন্ন করার চেয়ে সহজ, যদি আপনার দেওয়া ফাইলের জন্য একটি নির্দিষ্ট মান সহ সমস্ত কিছু সরিয়ে ফেলতে হয় তবে কেন কেবল গ্রেপ-ভি করবেন না:

উদাহরণস্বরূপ, দ্বিতীয় স্থান লাইনে "কল 2" মান সহ সমস্ত কিছু মুছতে: কল 1, কল 2, কল 3, কল 4

grep -v ',col2,' file > file_minus_offending_lines

যদি এটি যথেষ্ট পরিমাণে ভাল না হয়, কারণ কিছু লাইনে অন্যের কলামে সম্ভবত মিলের মানটি প্রদর্শিত হওয়ার কারণে ভুলভাবে ছত্রভঙ্গ হয়ে যায়, আপনি এরকম কিছু করতে পারেন:

আপত্তিজনক আপত্তিজনক কলামটি বিচ্ছিন্ন করতে: যেমন

awk -F, '{print $2 "|" $line}'

-F ক্ষেত্রটি ",", $ 2 -তে কলাম 2 এর পরে সীমানা নির্ধারণ করে, তারপরে কিছু কাস্টম ডিলিমিটার এবং তারপরে সম্পূর্ণ লাইন। তারপরে আপনি আপত্তিকর মান দিয়ে শুরু হওয়া লাইনগুলি সরিয়ে ফিল্টার করতে পারবেন :

 awk -F, '{print $2 "|" $line}' | grep -v ^BAD_VALUE

এবং তারপরে ডিলিমিটারের আগে জিনিসগুলি সরিয়ে ফেলুন:

awk -F, '{print $2 "|" $line}' | grep -v ^BAD_VALUE | sed 's/.*|//g'

(দ্রষ্টব্য - সেড কমান্ডটি opালু কারণ এটির মধ্যে পালানোর মান অন্তর্ভুক্ত নয় Also এছাড়াও সেড প্যাটার্নটি সত্যই "[^ |] +" (অর্থাত্ ডিলিমিটারের মতো কিছু নয়) হওয়া উচিত But তবে আশা করি এটি যথেষ্ট স্পষ্ট।


3
তিনি লাইনগুলি শুদ্ধ করতে চান না, তিনি একটি নির্দিষ্ট স্ট্রিং সহ একটি লাইনের একক অনুলিপি ধরে রাখতে চান। ইউনিক সঠিক ব্যবহারের মামলা।
in

-3

sortপ্রথমে ফাইলটি বাছাই করার পরে আপনি আবেদন করতে পারবেনuniq

মনে হচ্ছে ফাইলটি ঠিকঠাক করে দেওয়া হয়েছে:

$ cat test.csv
overflow@domain2.com,2009-11-27 00:58:29.793000000,xx3.net,255.255.255.0
stack2@domain.com,2009-11-27 01:05:47.893000000,xx2.net,127.0.0.1
overflow@domain2.com,2009-11-27 00:58:29.646465785,2x3.net,256.255.255.0 
stack2@domain.com,2009-11-27 01:05:47.893000000,xx2.net,127.0.0.1
stack3@domain.com,2009-11-27 01:05:47.893000000,xx2.net,127.0.0.1
stack4@domain.com,2009-11-27 01:05:47.893000000,xx2.net,127.0.0.1
stack2@domain.com,2009-11-27 01:05:47.893000000,xx2.net,127.0.0.1

$ sort test.csv
overflow@domain2.com,2009-11-27 00:58:29.646465785,2x3.net,256.255.255.0 
overflow@domain2.com,2009-11-27 00:58:29.793000000,xx3.net,255.255.255.0
stack2@domain.com,2009-11-27 01:05:47.893000000,xx2.net,127.0.0.1
stack2@domain.com,2009-11-27 01:05:47.893000000,xx2.net,127.0.0.1
stack2@domain.com,2009-11-27 01:05:47.893000000,xx2.net,127.0.0.1
stack3@domain.com,2009-11-27 01:05:47.893000000,xx2.net,127.0.0.1
stack4@domain.com,2009-11-27 01:05:47.893000000,xx2.net,127.0.0.1

$ sort test.csv | uniq
overflow@domain2.com,2009-11-27 00:58:29.646465785,2x3.net,256.255.255.0 
overflow@domain2.com,2009-11-27 00:58:29.793000000,xx3.net,255.255.255.0
stack2@domain.com,2009-11-27 01:05:47.893000000,xx2.net,127.0.0.1
stack3@domain.com,2009-11-27 01:05:47.893000000,xx2.net,127.0.0.1
stack4@domain.com,2009-11-27 01:05:47.893000000,xx2.net,127.0.0.1

আপনি কিছু AWK যাদুও করতে পারেন:

$ awk -F, '{ lines[$1] = $0 } END { for (l in lines) print lines[l] }' test.csv
stack2@domain.com,2009-11-27 01:05:47.893000000,xx2.net,127.0.0.1
stack4@domain.com,2009-11-27 01:05:47.893000000,xx2.net,127.0.0.1
stack3@domain.com,2009-11-27 01:05:47.893000000,xx2.net,127.0.0.1
overflow@domain2.com,2009-11-27 00:58:29.646465785,2x3.net,256.255.255.0 

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

1
হ্যাঁ তুমিই ঠিক. সর্বশেষ উদাহরণটি প্রশ্নটি যা চেয়েছিল তা করে, যদিও গৃহীত উত্তরটি অনেক পরিষ্কার থাকে। সংক্রান্ত sort, তারপর uniq, sortকাজ করার আগে সম্পন্ন করা প্রয়োজন uniqঅন্যথায় এটা কাজ করে না (কিন্তু আপনি দ্বিতীয় কমান্ড এবং মাত্র ব্যবহার এড়িয়ে যেতে পারেন sort -u)। থেকে uniq(1): "ইনপুট (বা স্ট্যান্ডার্ড ইনপুট) থেকে সংলগ্ন মিলের লাইনগুলি ফিল্টার করুন, OUTPUT (বা স্ট্যান্ডার্ড আউটপুট) এ লেখা" "
মিকায়েল এস

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