ইউনিক্সে কোনও ফাইলে নকল লাইনগুলি মুছার উপায় আছে?
আমি এটা করতে পারেন sort -u
এবং uniq
কমান্ড, কিন্তু আমি ব্যবহার করতে চান sed
বা awk
। এটা কি সম্ভব?
awk
, তবে এটি বড় ফাইলগুলিতে যথেষ্ট সংস্থান হবে।
ইউনিক্সে কোনও ফাইলে নকল লাইনগুলি মুছার উপায় আছে?
আমি এটা করতে পারেন sort -u
এবং uniq
কমান্ড, কিন্তু আমি ব্যবহার করতে চান sed
বা awk
। এটা কি সম্ভব?
awk
, তবে এটি বড় ফাইলগুলিতে যথেষ্ট সংস্থান হবে।
উত্তর:
awk '!seen[$0]++' file.txt
seen
এমন একটি সহযোগী-অ্যারে যা আওক ফাইলের প্রতিটি লাইন পাস করবে। যদি কোনও লাইন অ্যারে না থাকে তবে seen[$0]
মিথ্যাতে মূল্যায়ন করবে। !
একটি লজিক্যাল নয় অপারেটর এবং সত্য মিথ্যা invert হবে। আওক সেই লাইনগুলি মুদ্রণ করবে যেখানে অভিব্যক্তিটি সত্য হিসাবে মূল্যায়ণ করে। ++
বাড়তি seen
যাতে seen[$0] == 1
প্রথমবার পর একটি লাইন পাওয়া যায় এবং তারপর seen[$0] == 2
, ইত্যাদি।
Awk সবকিছু কিন্তু মূল্যায়ণ 0
এবং ""
সত্যতে (খালি স্ট্রিং)। যদি একটি সদৃশ লাইন স্থাপন করা হয় seen
তবে !seen[$0]
এটি মিথ্যাতে মূল্যায়ন করবে এবং আউটপুটটিতে লাইনটি লেখা হবে না।
awk '!seen[$0]++' merge_all.txt > output.txt
for f in *.txt; do gawk -i inplace '!seen[$0]++' "$f"; done
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'
$!
অংশ প্রয়োজনীয়? না sed 'N; /^\(.*\)\n\1$/!P; D'
একই জিনিস করে? আমি আমার মেশিনে দুজন আলাদা হওয়ার উদাহরণটি সামনে আসতে পারছি না (শেষ পর্যন্ত আমি উভয় সংস্করণ দিয়ে একটি খালি লাইন চেষ্টা করেছিলাম এবং তারা উভয়ই ভাল ছিল)।
[ -~]
0x20 (স্পেস) থেকে 0x7E (টিলডে) পর্যন্ত অনেকগুলি এএসসিআইআই অক্ষর উপস্থাপন করে। এগুলি মুদ্রণযোগ্য ASCII অক্ষর হিসাবে বিবেচিত হয় (লিঙ্কযুক্ত পৃষ্ঠায় 0x7F / মুছে ফেলা হয় তবে এটি ঠিক মনে হয় না)। যে সমাধান যে কেউ হওয়া ASCII কেউ ব্যবহার বলে, ট্যাব অক্ষর ব্যবহার করে না ভাঙ্গা .. আরো পোর্টেবল তোলে [^\n]
ছাড়া আরো অনেক কিছুর সাথে অক্ষর অন্তর্ভুক্ত ... ই.এম. এর 'সব, আসলে।
পারল ওয়ান-লাইনার @ জোনাসের অ্যাডক সমাধানের অনুরূপ:
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
আন্ড্রে মিলার উপরে যে ওয়ান-লাইনার পোস্ট করেছেন সেগুলি সাম্প্রতিক সংস্করণের সেড ব্যতীত কাজ করে যখন ইনপুট ফাইলটি ফাঁকা লাইন এবং কোনও অক্ষর দিয়ে শেষ হয়। আমার ম্যাকে আমার সিপিইউ কেবল স্পিন করে।
অসীম লুপটি যদি শেষ লাইনটি ফাঁকা হয় এবং কোনও অক্ষর থাকে :
sed '$!N; /^\(.*\)\n\1$/!P; D'
ঝুলন্ত নয়, তবে আপনি শেষ লাইনটি হারাবেন
sed '$d;N; /^\(.*\)\n\1$/!P; D'
ব্যাখ্যাটি সেড এফএকিউর একেবারে শেষে :
জিএনইউ সেড রক্ষণাবেক্ষণকারী মনে করেছিলেন যে বহনযোগ্য সমস্যাজনিত সমস্যা সত্ত্বেও
, এন কমান্ডটি মুদ্রণের পরিবর্তে (
মুছে ফেলার পরিবর্তে ) প্যাটার্ন স্পেসটি
"পরবর্তী পংক্তিকে যুক্ত করার" আদেশটি কীভাবে আচরণ করা উচিত সে সম্পর্কে তার অন্তর্দৃষ্টিগুলির সাথে আরও সুসংগত ছিল ।
পরিবর্তনের পক্ষে অন্য আরেকটি বিষয় হ'ল "{N; কমান্ড;}"
ফাইলের বিজোড় সংখ্যার লাইন থাকলে শেষ লাইনটি মুছে ফেলবে, তবে ফাইলটিতে লাইন সংখ্যা সমেত
যদি শেষ লাইনটি মুদ্রণ করবে।যে সমস্ত স্ক্রিপ্টগুলি এন এর পূর্বের আচরণ ব্যবহার করেছিল (
ইওএফ পৌঁছানোর পরে প্যাটার্ন স্পেস মুছে ফেলছে ) সেডের
সমস্ত সংস্করণের সাথে সামঞ্জস্যপূর্ণ স্ক্রিপ্টগুলিতে রূপান্তর করতে , একটি লোন পরিবর্তন করুন "এন;" "$ d; N;" ।
$ 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.
ব্যাখ্যা করে:
$!N;
: যদি বর্তমান লাইনটি সর্বশেষ লাইন না হয় N
তবে পরবর্তী লাইনটি পড়তে কমান্ডটি ব্যবহার করুন pattern space
।/^(.*)\n\1$/!P
: যদি কারেন্টের বিষয়বস্তুগুলি pattern space
দুটি duplicate string
দ্বারা পৃথক করা হয় \n
, যার অর্থ পরবর্তী লাইনের same
সাথে বর্তমান লাইনের সাথে হ'ল , আমরা আমাদের মূল ধারণা অনুযায়ী এটি মুদ্রণ করতে পারি না; অন্যথায়, যার অর্থ বর্তমান লাইনটি তার সমস্ত সদৃশ লাইনগুলির সর্বশেষতম উপস্থিতি, আমরা এখন বর্তমান ব্যবহারে অক্ষরগুলি P
মুদ্রণের জন্য কমান্ড ব্যবহার করতে পারি ( এছাড়াও মুদ্রিত)।pattern space
\n
\n
D
: আমরা D
বর্তমান ব্যবহারের অক্ষর মুছে ফেলার জন্য কমান্ডটি ব্যবহার করি ( এছাড়াও মুছে pattern space
ফেলাও ), তারপরের লিখিত অংশটি পরের লাইনে।\n
\n
pattern space
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.
ব্যাখ্যা করে:
:loop
কমান্ড একটি label
নাম সেট loop
।N
পরের লাইন পড়তে ব্যবহার করুন pattern space
।s/^(.*)\n\1$/\1/
বর্তমান লাইনটি যদি বর্তমান লাইনের সাথে একই থাকে তবে মুছে ফেলতে ব্যবহার করুন , আমরা ক্রিয়াটি করতে s
কমান্ডটি ব্যবহার করি delete
।s
কমান্ড সফলভাবে মৃত্যুদন্ড কার্যকর করা হয়, তাহলে ব্যবহার tloop
কমান্ড বাহিনী sed
ঝাঁপ label
নামে loop
, util সেখানে লাইন যার কোন সদৃশ পরপর লাইন আছে যা পরবর্তী লাইনে একই লুপ কি করতে হবে latest printed
; অন্যথায়, লাইনটি একইরূপে D
কমান্ডটি ব্যবহার করুন এবং প্রথম কমান্ডে লাফিয়ে পড়তে বাধ্য করুন , যা কমান্ড, বর্তমানের বিষয়বস্তুটি পরবর্তী নতুন লাইন।delete
latest-printed line
sed
p
pattern space
busybox echo -e "1\n2\n2\n3\n3\n3\n4\n4\n4\n4\n5" | busybox sed -nr "$!N;/^(.*)\n\1$/!P;D"
cat filename | sort | uniq -c | awk -F" " '$1<2 {print $2}'
ডাব্লিকেট লাইনগুলি awk ব্যবহার করে মুছে ফেলে।
cat
অকেজো। যাইহোক, uniq
ইতিমধ্যে এটি নিজে থেকেই এটি করে এবং প্রতি লাইনে ইনপুটটির ঠিক এক শব্দ হওয়া দরকার না be
uniq
একা যথেষ্ট।