কোনও ফাইলকে ইউনিক্সে বাছাই না করে নকল লাইনগুলি কীভাবে মুছবেন?


136

ইউনিক্সে কোনও ফাইলে নকল লাইনগুলি মুছার উপায় আছে?

আমি এটা করতে পারেন sort -uএবং uniqকমান্ড, কিন্তু আমি ব্যবহার করতে চান sedবা awk। এটা কি সম্ভব?


11
আপনি যদি টানা ডুপ্লিকেট বলতে চান তবে uniqএকা যথেষ্ট।
মাইকেল ক্রেলিন - হ্যাকার

এবং অন্যথায়, আমি বিশ্বাস করি এটি এটি দিয়ে সম্ভব awk, তবে এটি বড় ফাইলগুলিতে যথেষ্ট সংস্থান হবে।
মাইকেল ক্রেলিন - হ্যাকার

সদৃশ স্ট্যাকওভারফ্লো.com / q/ 24324350 এবং স্ট্যাকওভারফ্লো. com/q / 11532157 এর আকর্ষণীয় উত্তর রয়েছে যা আদর্শভাবে এখানে স্থানান্তরিত হওয়া উচিত should
ট্রিপলি

উত্তর:


290
awk '!seen[$0]++' file.txt

seenএমন একটি সহযোগী-অ্যারে যা আওক ফাইলের প্রতিটি লাইন পাস করবে। যদি কোনও লাইন অ্যারে না থাকে তবে seen[$0]মিথ্যাতে মূল্যায়ন করবে। !একটি লজিক্যাল নয় অপারেটর এবং সত্য মিথ্যা invert হবে। আওক সেই লাইনগুলি মুদ্রণ করবে যেখানে অভিব্যক্তিটি সত্য হিসাবে মূল্যায়ণ করে। ++বাড়তি seenযাতে seen[$0] == 1প্রথমবার পর একটি লাইন পাওয়া যায় এবং তারপর seen[$0] == 2, ইত্যাদি।
Awk সবকিছু কিন্তু মূল্যায়ণ 0এবং ""সত্যতে (খালি স্ট্রিং)। যদি একটি সদৃশ লাইন স্থাপন করা হয় seenতবে !seen[$0]এটি মিথ্যাতে মূল্যায়ন করবে এবং আউটপুটটিতে লাইনটি লেখা হবে না।


5
কোনও ফাইলে এটি সংরক্ষণ করতে আমরা এটি করতে পারিawk '!seen[$0]++' merge_all.txt > output.txt
আকাশ কান্দপাল

5
এখানে একটি গুরুত্বপূর্ণ সাবধানবাণী: যদি আপনার একাধিক ফাইলের জন্য এটি করতে হয় এবং আপনি কমান্ডের শেষে আরও ফাইলগুলি পরীক্ষা করেন বা একটি ওয়াইল্ডকার্ড ব্যবহার করেন ... 'দেখা' অ্যারে সমস্ত ফাইলের নকল লাইন পূরণ করবে। পরিবর্তে আপনি যদি প্রতিটি ফাইল স্বাধীনভাবে চিকিত্সা করতে চান তবে আপনাকে এমন কিছু করতে হবেfor f in *.txt; do gawk -i inplace '!seen[$0]++' "$f"; done
নিক কে 9

@ নিক কে 9 যে একাধিক ফাইল জুড়ে চূড়ান্তভাবে ডি-ডুপিং করা নিজেই দুর্দান্ত। সুন্দর টিপ
21

31

Http://sed.sourceforge.net/sed1line.txt থেকে : (দয়া করে আমাকে জিজ্ঞাসা করবেন না এটি কীভাবে কাজ করে ;-))

 # delete duplicate, consecutive lines from a file (emulates "uniq").
 # First line in a set of duplicate lines is kept, rest are deleted.
 sed '$!N; /^\(.*\)\n\1$/!P; D'

 # delete duplicate, nonconsecutive lines from a file. Beware not to
 # overflow the buffer size of the hold space, or else use GNU sed.
 sed -n 'G; s/\n/&&/; /^\([ -~]*\n\).*\n\1/d; s/\n//; h; P'

geekery ;-) +1, কিন্তু সম্পদ খরচ অনিবার্য।
মাইকেল ক্রেলিন - হ্যাকার

3
! '$ এন; /^(.*)\n\1$/!P; ডি'র অর্থ "যদি আপনি শেষ লাইনে না থাকেন তবে অন্য লাইনে পড়ুন Now এখন আপনার কী আছে তা দেখুন এবং এটি যদি নতুন লাইনের পরে স্টাফ না হয় এবং একই জিনিসটি আবার একই জিনিসটি মুদ্রণ করে Now এখন মুছুন delete স্টাফ (নিউলাইন পর্যন্ত) "
বিটা

2
'জি; S / \ N / && /; / ^ ([[- ~] * \ n)। * \ n \ 1 / ডি; S / \ N //; জ; পি'র অর্থ মোটামুটি, "পুরো হোল্ড স্পেসটি এই লাইনটি যুক্ত করুন, তারপরে যদি আপনি কোনও নকল লাইন দেখতে পান তবে পুরো জিনিসটি হোল্ড স্পেসে আবার কপি করুন এবং প্রথম অংশটি মুদ্রণ করুন (আপনি যে রেখাটি ঠিক সেই লাইনে রেখেছেন) পড়ুন। "
বিটা

কি $!অংশ প্রয়োজনীয়? না sed 'N; /^\(.*\)\n\1$/!P; D'একই জিনিস করে? আমি আমার মেশিনে দুজন আলাদা হওয়ার উদাহরণটি সামনে আসতে পারছি না (শেষ পর্যন্ত আমি উভয় সংস্করণ দিয়ে একটি খালি লাইন চেষ্টা করেছিলাম এবং তারা উভয়ই ভাল ছিল)।
এডিডি

1
প্রায় 7 বছর পরে এবং উত্তর কেউই উত্তরসূচক উত্তর দেয় নি ... <সনিফ> আমাকে দু: খিত করে। ;) যাইহোক, [ -~]0x20 (স্পেস) থেকে 0x7E (টিলডে) পর্যন্ত অনেকগুলি এএসসিআইআই অক্ষর উপস্থাপন করে। এগুলি মুদ্রণযোগ্য ASCII অক্ষর হিসাবে বিবেচিত হয় (লিঙ্কযুক্ত পৃষ্ঠায় 0x7F / মুছে ফেলা হয় তবে এটি ঠিক মনে হয় না)। যে সমাধান যে কেউ হওয়া ASCII কেউ ব্যবহার বলে, ট্যাব অক্ষর ব্যবহার করে না ভাঙ্গা .. আরো পোর্টেবল তোলে [^\n]ছাড়া আরো অনেক কিছুর সাথে অক্ষর অন্তর্ভুক্ত ... ই.এম. এর 'সব, আসলে।
বি লেয়ার

14

পারল ওয়ান-লাইনার @ জোনাসের অ্যাডক সমাধানের অনুরূপ:

perl -ne 'print if ! $x{$_}++' file

এই প্রকরণটি তুলনার আগে পূর্ববর্তী সাদা স্থানটিকে সরিয়ে দেয়:

perl -lne 's/\s*$//; print if ! $x{$_}++' file

এই প্রকারভেদটি ফাইলটিকে জায়গায় জায়গায় সম্পাদনা করে:

perl -i -ne 'print if ! $x{$_}++' file

এই প্রকারভেদ ফাইলটিকে জায়গায় জায়গায় সম্পাদনা করে এবং একটি ব্যাকআপ দেয় file.bak

perl -i.bak -ne 'print if ! $x{$_}++' file

6

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

অসীম লুপটি যদি শেষ লাইনটি ফাঁকা হয় এবং কোনও অক্ষর থাকে :

sed '$!N; /^\(.*\)\n\1$/!P; D'

ঝুলন্ত নয়, তবে আপনি শেষ লাইনটি হারাবেন

sed '$d;N; /^\(.*\)\n\1$/!P; D'

ব্যাখ্যাটি সেড এফএকিউর একেবারে শেষে :

জিএনইউ সেড রক্ষণাবেক্ষণকারী মনে করেছিলেন যে বহনযোগ্য সমস্যাজনিত সমস্যা সত্ত্বেও
, এন কমান্ডটি মুদ্রণের পরিবর্তে (
মুছে ফেলার পরিবর্তে ) প্যাটার্ন স্পেসটি
"পরবর্তী পংক্তিকে যুক্ত করার" আদেশটি কীভাবে আচরণ করা উচিত সে সম্পর্কে তার অন্তর্দৃষ্টিগুলির সাথে আরও সুসংগত ছিল ।
পরিবর্তনের পক্ষে অন্য আরেকটি বিষয় হ'ল "{N; কমান্ড;}"
ফাইলের বিজোড় সংখ্যার লাইন থাকলে শেষ লাইনটি মুছে ফেলবে, তবে ফাইলটিতে লাইন সংখ্যা সমেত
যদি শেষ লাইনটি মুদ্রণ করবে।

যে সমস্ত স্ক্রিপ্টগুলি এন এর পূর্বের আচরণ ব্যবহার করেছিল (
ইওএফ পৌঁছানোর পরে প্যাটার্ন স্পেস মুছে ফেলছে ) সেডের
সমস্ত সংস্করণের সাথে সামঞ্জস্যপূর্ণ স্ক্রিপ্টগুলিতে রূপান্তর করতে , একটি লোন পরিবর্তন করুন "এন;" "$ d; N;"


5

ভিম (vi সামঞ্জস্যপূর্ণ) ব্যবহার করে একটি বিকল্প উপায় :

একটি ফাইল থেকে নকল, একটানা লাইন মুছুন:

vim -esu NONE +'g/\v^(.*)\n\1$/d' +wq

কোনও ফাইল থেকে সদৃশ, নন-সংযুক্ত এবং নিখরচায় লাইনগুলি মুছুন:

vim -esu NONE +'g/\v^(.+)$\_.{-}^\1$/d' +wq


4

প্রথম সমাধানটি http://sed.sourceforge.net/sed1line.txt থেকেও

$ echo -e '1\n2\n2\n3\n3\n3\n4\n4\n4\n4\n5' |sed -nr '$!N;/^(.*)\n\1$/!P;D'
1
2
3
4
5

মূল ধারণাটি হ'ল:

print ONLY once of each duplicate consecutive lines at its LAST appearance and use D command to implement LOOP.

ব্যাখ্যা করে:

  1. $!N;: যদি বর্তমান লাইনটি সর্বশেষ লাইন না হয় Nতবে পরবর্তী লাইনটি পড়তে কমান্ডটি ব্যবহার করুন pattern space
  2. /^(.*)\n\1$/!P: যদি কারেন্টের বিষয়বস্তুগুলি pattern spaceদুটি duplicate stringদ্বারা পৃথক করা হয় \n, যার অর্থ পরবর্তী লাইনের sameসাথে বর্তমান লাইনের সাথে হ'ল , আমরা আমাদের মূল ধারণা অনুযায়ী এটি মুদ্রণ করতে পারি না; অন্যথায়, যার অর্থ বর্তমান লাইনটি তার সমস্ত সদৃশ লাইনগুলির সর্বশেষতম উপস্থিতি, আমরা এখন বর্তমান ব্যবহারে অক্ষরগুলি Pমুদ্রণের জন্য কমান্ড ব্যবহার করতে পারি ( এছাড়াও মুদ্রিত)।pattern space\n\n
  3. D: আমরা Dবর্তমান ব্যবহারের অক্ষর মুছে ফেলার জন্য কমান্ডটি ব্যবহার করি ( এছাড়াও মুছে pattern spaceফেলাও ), তারপরের লিখিত অংশটি পরের লাইনে।\n\npattern space
  4. এবং Dকমান্ডটি sedতার FIRSTকমান্ডে ঝাঁপিয়ে $!Nপড়তে বাধ্য করবে , তবে ফাইল বা স্ট্যান্ডার্ড ইনপুট স্ট্রিম থেকে পরবর্তী লাইনটি পড়বে না।

দ্বিতীয় সমাধানটি বোঝা সহজ (নিজের কাছ থেকে):

$ echo -e '1\n2\n2\n3\n3\n3\n4\n4\n4\n4\n5' |sed -nr 'p;:loop;$!N;s/^(.*)\n\1$/\1/;tloop;D'
1
2
3
4
5

মূল ধারণাটি হ'ল:

print ONLY once of each duplicate consecutive lines at its FIRST appearance and use : command & t command to implement LOOP.

ব্যাখ্যা করে:

  1. ইনপুট স্ট্রিম বা ফাইল থেকে একটি নতুন লাইন পড়ুন এবং এটি একবার মুদ্রণ করুন।
  2. ব্যবহার :loopকমান্ড একটি labelনাম সেট loop
  3. Nপরের লাইন পড়তে ব্যবহার করুন pattern space
  4. s/^(.*)\n\1$/\1/বর্তমান লাইনটি যদি বর্তমান লাইনের সাথে একই থাকে তবে মুছে ফেলতে ব্যবহার করুন , আমরা ক্রিয়াটি করতে sকমান্ডটি ব্যবহার করি delete
  5. যদি sকমান্ড সফলভাবে মৃত্যুদন্ড কার্যকর করা হয়, তাহলে ব্যবহার tloopকমান্ড বাহিনী sedঝাঁপ labelনামে loop, util সেখানে লাইন যার কোন সদৃশ পরপর লাইন আছে যা পরবর্তী লাইনে একই লুপ কি করতে হবে latest printed; অন্যথায়, লাইনটি একইরূপে Dকমান্ডটি ব্যবহার করুন এবং প্রথম কমান্ডে লাফিয়ে পড়তে বাধ্য করুন , যা কমান্ড, বর্তমানের বিষয়বস্তুটি পরবর্তী নতুন লাইন।deletelatest-printed linesedppattern space

সাথে, busybox Windows এ একই কমান্ডbusybox echo -e "1\n2\n2\n3\n3\n3\n4\n4\n4\n4\n5" | busybox sed -nr "$!N;/^(.*)\n\1$/!P;D"
মেথর

-1

এটি লাইন নীচে awk ব্যবহার করে অর্জন করা যেতে পারে
অনন্য মানগুলি প্রদর্শন করবে

awk file_name | uniq

আপনি এই অনন্য মানগুলি একটি নতুন ফাইলে আউটপুট করতে পারেন

awk file_name | uniq > uniq_file_name

নতুন ফাইল ইউনিক_ফাইল_নামে কেবল অনন্য মান থাকবে, কোনও সদৃশ নেই


-4
cat filename | sort | uniq -c | awk -F" " '$1<2 {print $2}'

ডাব্লিকেট লাইনগুলি awk ব্যবহার করে মুছে ফেলে।


1
এটি লাইনের ক্রমকে বিঘ্নিত করবে।
বিজয়

1
20 জিবি পাঠ্য ফাইলটি কী? অত্যন্ত ধীর.
আলেকজান্ডার লুবাইগিন

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