লাইনের ক্রম বজায় রেখে সদৃশ লাইনগুলি সরান


14
[root@server]# awk '!seen[$0]++' out.txt > cleaned
awk: (FILENAME=out.txt FNR=8547098) fatal error: internal error
Aborted
[root@server]#

"" সার্ভার "" এর মধ্যে রয়েছে: 8 গিগাবাইট র‌্যাম + 16 গিগাবাইট সোয়াপ, এক্স> 300 জিবিাইট ফ্রি স্পেস, এমডি 64, ডেস্কটপ সিপিইউ। বৈজ্ঞানিক লিনাক্স 6.6। LOAD করতে এর বাইরে আর কিছুই চালায় না। কয়েক সেকেন্ডের পরে ওউকে বাতিল করা হয় .. out.txt হল ~ 1.6 গিগাবাইট। জিএনইউ অ্যাওক 3.1.7।

প্রশ্ন : লাইনের ক্রম বজায় রেখে আমি কীভাবে সদৃশ লাইনগুলি সরিয়ে ফেলতে পারি? কেসটিও গুরুত্বপূর্ণ, প্রাক্তন: "এ" এবং "ক" দুটি ভিন্ন লাইন, এটি রাখতে হবে। তবে "এ" এবং "এ" সদৃশ, কেবল প্রথমটির প্রয়োজন।

উত্তর যে কোনও কিছুতে থাকতে পারে .. যদি এই জন্য জারজ ভাল না হয় .. তবে পার্ল / সেড .. সমস্যা কী হতে পারে?

[root@server]# ulimit -a
core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 61945
max locked memory       (kbytes, -l) 99999999
max memory size         (kbytes, -m) unlimited
open files                      (-n) 999999
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 99999999
cpu time               (seconds, -t) unlimited
max user processes              (-u) 61945
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited
[root@server]# 

আপডেট: আমি এটি একটি আরএইচইএল মেশিনে চেষ্টা করেছিলাম, এটি বাতিল হয় না, তবে এটি শেষ হওয়ার জন্য অপেক্ষা করার আমার কাছে সময় ছিল না .. কেন এসএল লিনাক্স আরএইচইএল থেকে আলাদা?

আপডেট: আমি একটি উবুন্টু 14 ভার্চুয়াল অনুমানের চেষ্টা করছি .. এখনও পর্যন্ত এটি কার্যকর! এটি কোনও ওলিমিট সমস্যা নয়: ম্যাক 1.3.3

root@asdf-VirtualBox:~# ulimit -a
core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 51331
max locked memory       (kbytes, -l) 64
max memory size         (kbytes, -m) unlimited
open files                      (-n) 1024
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) 51331
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited
root@asdf-VirtualBox:~# 

2
আপনার উদাহরণে কোনও সদৃশ লাইন নেই ...?
মাইকজার্ভ

1
awkদুটি মেশিনে সংস্করণগুলি কী কী ?
cuonglm

আপ-টু-ডেট রেল এবং আপ টু ডেট এসএল লিনাক্স, রেলের সংস্করণটি জানেন না .. এসএল: জিএনইউ
অব্ক

কত বড় out.txt? আপনি যদি একটি ছোট ফাইলটিতে চেষ্টা করে থাকেন তবে একই আদেশটি কি কাজ করে? মেশিনে কতজন ব্যবহারকারী? প্রক্রিয়াটির জন্য যথেষ্ট উপলব্ধ মেমরি ছিল? ইনপুট ফাইলের 8547098 লাইন সম্পর্কে বিশেষ কিছু আছে?
টেরডন

উত্তর:


22

আমি সন্দেহ করি এটি একটি পার্থক্য আনবে তবে কেবলমাত্র পার্লে একই জিনিসটি কীভাবে করা যায় তা এখানে:

perl -ne 'print if ++$k{$_}==1' out.txt

যদি সমস্যাটি মেমোরিতে অনন্য লাইনগুলি রাখে তবে awkআপনি যা চেষ্টা করেছেন তেমন সমস্যা থাকবে । সুতরাং, অন্য পদ্ধতির হতে পারে:

cat -n out.txt | sort -k2 -k1n  | uniq -f1 | sort -nk1,1 | cut -f2-

কিভাবে এটা কাজ করে:

  1. একটি জিএনইউ সিস্টেমে cat -nকিছু পরিমাণ ফাঁকা স্থান অনুসরণ করে <ট্যাব> অক্ষর অনুসরণ করে প্রতিটি লাইনে লাইন নম্বরটি প্রতিপাদন করা হবে । catপাইপ এই ইনপুট প্রতিনিধিত্ব sort

  2. sortএর -k2বিকল্পটি বাছাই করার সময় লাইনের শেষ অবধি দ্বিতীয় ক্ষেত্রের অক্ষরগুলি বিবেচনা করার জন্য নির্দেশ দেয় এবং sortসাদা-স্পেসে ডিফল্টরূপে ক্ষেত্রগুলি বিভক্ত করে (বা cat'sertedোকানো স্পেস এবং <ট্যাব> )
    এর পরে -k1n, sortদ্বিতীয় ক্ষেত্রটিকে প্রথমে বিবেচনা করে এবং দ্বিতীয়ত - অভিন্ন -k2ক্ষেত্রগুলির ক্ষেত্রে - এটি প্রথম ক্ষেত্রটিকে বিবেচনা করে তবে সংখ্যার ভিত্তিতে বাছাই করা হিসাবে বিবেচনা করে। সুতরাং পুনরাবৃত্তি লাইন একসাথে বাছাই করা হবে কিন্তু ক্রম তারা হাজির।

  3. ফলাফলগুলি পাইপ করা হয় uniq- যাকে বলা হয় প্রথম ক্ষেত্রটি উপেক্ষা করতে বলা হয় ( -f1- এবং পাশাপাশি সাদা অংশ দ্বারা পৃথক করা) - যার ফলে মূল ফাইলের অনন্য লাইনের একটি তালিকা তৈরি হয় এবং এতে ফিরে পাইপ করা হয় sort
  4. এবার sortপ্রথম ক্ষেত্রটিতে ( catসন্নিবেশ করা লাইন নম্বরটি) সংখ্যাগতভাবে বাছাই করুন, মূল ফাইলটিতে যা ছিল তা সাজানোর ক্রম পেয়ে এই ফলাফলগুলিকে পাইপ দেয় cut
  5. শেষ অবধি, cutসন্নিবেশ করা লাইন নম্বরগুলি সরিয়ে দেয় cat। এটি cutকেবল ২ য় ক্ষেত্রের মধ্য দিয়ে রেখার শেষের মাধ্যমে মুদ্রণ দ্বারা প্রভাবিত হবে (এবং cutএর ডিফল্ট ডিলিমিটার একটি <ট্যাব> অক্ষর)

বর্ণনা করা:

$ cat file
bb
aa
bb
dd
cc
dd
aa
bb
cc
$ cat -n file | sort -k2 | uniq -f1 | sort -k1 | cut -f2-
bb
aa    
dd
cc

হাই টেরডন, ওপিকে লাইনের ক্রম রাখা দরকার, সুতরাং বিড়াল | সাজানো | ইউনিট পদ্ধতিটি চলবে না ... যদিও আপনার পার্ল সংস্করণটির মতো ...
ল্যামবার্ট

1
সাথে চমৎকার সমাধান sort! কিন্তু sortকরতে পারি না uniqনিজে যাতে আপনি সংক্ষিপ্ত তুমি কি স্ক্রিপ্ট দ্বারা sort -uk2 | sort -bk1,1n
Costas

@ কাস্টাস এটি সবচেয়ে বেশি sort? আমি ভেবেছিলাম -uএকটি জিএনইউ বৈশিষ্ট্য।
টেরডন

@ ডন_ক্রিসটি আহ, তাই তাই, ধন্যবাদ যদিও আমি এখানে এটি ব্যবহার করতে পারি? আমি যেমন লক্ষ্য করেছি (এবং ঠিক করার জন্য সম্পাদিত), লাইন ক্রম ধরে রাখার জন্য আমাকে প্রথমে ২ য় ক্ষেত্র এবং তারপরে প্রথম সংখ্যাতে বাছাই করতে হবে। তারপরে আমি কীভাবে -uএটি ব্যবহার এবং নির্দিষ্ট করতে পারি যে এটির প্রথম ক্ষেত্রটিকে উপেক্ষা করা উচিত? মতে man sort, এটি -uসম্ভাব্য বিকল্পগুলির মধ্যে একটি নয় -f, সুতরাং এটি এখানে ব্যবহার করা যাবে বলে আমার মনে হয় না।
টেরডন

1
এই শোয়ার্তজিয়ান রূপান্তর ! (+1)
জাজাও

7
#!/usr/bin/perl 
use DB_File;
tie %h, 'DB_File';

while(<>){ not $h{$_} and print and $h{$_}=1 }

সম্পাদনা 1: এটি কি সত্যিই কাজ করে? (তুলনা)

Sol1 : Terdon et all Schwartzian-transform-like one-liner
    cat -n _1 | sort -uk2 | sort -nk1 | cut -f2-

Sol2 : perl  + DB_File (this answer)
    perl dbfile-uniq _1

Sol3 : PO (John W. Gill solution has a similar behavior)
    awk '!seen[$0]++' _1

Sol4: Terdon perl
    perl -ne 'print if ++$k{$_}==1' _1

কেস 1 : 100_000_000 এলোমেলো সংখ্যা (প্রতিটি 5 ডিজিট), 566 এমবিটস, 31_212 বিভিন্ন মান:

$ while true ; do echo $RANDOM; done | head -100000000 > _1

কেস 2 : 50_000_000 র‌্যান্ড নম্বর (প্রতিটি 10 ​​টি সংখ্যা), 516 এমবাইটস, 48_351_464 বিভিন্ন মান:

$ shuf _1 |  sed 'N;s/\n/ /' > _11

(নিম্নলিখিত সংখ্যাগুলি খুব সুনির্দিষ্ট নয়):

┌────────┬────────┬────────────────┬────────┬──────┐
         Sol1    Sol2            Sol3    Sol4 
         sort...│ perl DB         awk     perl 
├────────┼────────┼────────────────┼────────┼──────┤
 case 1  6m15    6m17            0m28    0m28 
├────────┼────────┼────────────────┼────────┴──────┤
 case 2  11m15   81m44           out of memory 
├────────┼────────┼────────────────┼────────┬──────┤
 case 2          5m54 /cache=2G               
└────────┴────────┴────────────────┴────────┴──────┘

sol2 ক্যাশে সহ:

use DB_File;
use Fcntl ;

$DB_HASH->{'cachesize'} = 2000_000_000;
tie %h, 'DB_File', "_my.db", O_RDWR|O_CREAT|O_TRUNC, 0640, $DB_HASH;

while(<>){ not $h{$_} and print and $h{$_}=1 }

বাছাই করাও ক্যাশেস বিকল্প যুক্ত করে অপ্টিমাইজ করা যায় (সম্পন্ন হয়নি)।

একটি দ্রুত উপসংহার:

  • sort একটি দুর্দান্ত আদেশ!

1
sort -uk2এবং sort -nk1,1বিভিন্ন। প্রথমটি 2 সিসি কী থেকে রেখার শেষ পর্যন্ত বিবেচনা করে, দ্বিতীয়টি কেবল প্রথম কীটিকে বিবেচনা করে। আপনার sort -nk1সেখানে পরিবর্তন করা উচিত - এটি সেভাবে দ্রুততর হতে পারে তবে এটি অবশ্যই আরও নির্ভরযোগ্য হবে। যাইহোক - সেগুলি কিছু সুন্দর বাক্স।
মাইক্রজারভ

@ মাইকজার, মন্তব্যের জন্য আপনাকে ধন্যবাদ। যেমন কে 1,1 অনন্য, তাই সাজান -nk1 এবং সাজান -nk1,1 কিছু ফলাফল দেয়। আমি উভয় চেষ্টা করেছিলাম, ফলাফলটি একই ছিল এবং সময়টি আলাদা ছিল না।
জাজাও

এটি উপলব্ধি করে - যদিও এটি চেষ্টা করার জন্য ধন্যবাদ। সুতরাং cat -nএকটি ট্যাব আছে ? আমি জানি না যে কমান্ডটি কীভাবে কাজ করে।
মাইকসার্ভ

1
@mikeserv, সুখে cat -nপ্রতিটি transfrom lineমধ্যে spaces + the number + \t + lineসাজানোর কাটা জন্য আদর্শ ফরম্যাট -
JJoao

1

আমি ব্যবহার করেছি

awk -v BINMODE=rw '!($0 in a){a[$0];print}' infile >> outfile

বিনমোড = rw: লাইন টার্মিনেটরদের শেষ রাখার জন্য খুশি। (আমি একটি মিশ্র ওএস পরিবেশে থাকি)

যুক্তি সহজ।

যদি বর্তমান লাইনটি এসোসিয়েটিভ অ্যারেতে না থাকে তবে এটিকে এসোসিয়েটিভ অ্যারেতে যুক্ত করুন এবং আউটপুট প্রিন্ট করুন।

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


0

আপনার সমস্যার অর্ডার-সংরক্ষণের শব্দার্থবিজ্ঞানের একটি দুর্দান্ত সম্পত্তি রয়েছে: আপনি সমস্যাটিকে বিভাজন করতে পারেন। আপনি split -l 1000000ইনপুট ফাইলটিতে করতে পারেন ; এটি উত্পাদিত 1000000-লাইনের টুকরোগুলি অনুসারে নাম রয়েছে যা ভাল; তারপরে টুকরো টুকরো টুকরো করা; এবং তারপরে (দ্বিতীয় পাস হিসাবে) এর ফলাফলগুলি একীকৃত করুন।

এটি একটি বহুমাত্রিক সমাধানে রূপান্তরিত করার ব্যয়ে মেমরির বাইরে থাকা সমস্যার সমাধান করে (মেমরির প্রয়োজনীয়তাটি ক্যাপ করে)।

বিশেষ করে:

ইনপুট ডেটা তৈরি করুন:

$ cat make-uniqm-input.py
#!/usr/bin/env python
import random
n = 1000000
for i in xrange(0, n):
    print random.randint(1000, 2000)

$ python make-uniqm-input.py  > uniqm-input.txt

$ wc -l uniqm-input.txt
 1000000 uniqm-input.txt

ইনপুট ডেটা বিভক্ত করুন:

$ split -l 10000 uniqm-input.txt

$ ls x?? | head
xaa
xab
xac
xad
xae
xaf
xag
xah
xai
xaj

$ ls x?? | wc -l
     100

$ cat x?? | wc -l
 1000000

একসাথে একবারে চালনা করুন (স্মৃতিতে সমস্ত অনন্য ইনপুট লাইন ধরে রাখে):

# 'uniqm' is any order-preserving uniq implementation, such as
# gawk '!counts[$0]++'.
$ uniqm < uniqm-input.txt > output-no-splitting.txt

$ wc -l output-no-splitting.txt
    1001 output-no-splitting.txt

বিভক্ত টুকরাগুলিতে ইউনিকফায়ার চালান (মেমরির প্রতিটি টুকরো থেকে কেবল অনন্য ইনপুট লাইন ধরে রাখে), তারপরে দ্বিতীয় পাস হিসাবে হ্রাস করুন:

$ for x in x??; do uniqm < $x; done | uniqm > output-with-splitting.txt

$ wc -l output-with-splitting.txt
    1001 output-with-splitting.txt

তুলনা করা:

$ diff output-no-splitting.txt output-with-splitting.txt

$ head uniqm-input.txt
1506
1054
1623
1002
1173
1400
1226
1340
1824
1091

$ head output-with-splitting.txt
1506
1054
1623
1002
1173
1400
1226
1340
1824
1091

আমি আপনার ইনপুটটিতে অনন্য-অনন্য লাইনগুলির অনন্যের অনুপাত জানি না, অথবা ইনপুট লাইনগুলি কতটা ভালভাবে মিশ্রিত হয় - তাই আপনার প্রয়োজনীয় বিভাজনযুক্ত ফাইলগুলির সংখ্যার ক্ষেত্রে কিছু করার জন্য কিছু সুর আছে।


0

আরেকটি পদ্ধতির (পৃথক উত্তর হিসাবে পোস্ট করার উপযুক্ত) হ'ল: স্প্লিট-ফাইল পদ্ধতির পরিবর্তে যা অস্থায়ী ফাইল তৈরি করে, ইউফিকেশনকারী সফ্টওয়্যারটিতেই ব্যাচিং করুন। উদাহরণস্বরূপ, ব্যাখ্যামূলক উদ্দেশ্যে রুবি ইউকিফায়ার বাস্তবায়ন ব্যবহার:

require 'set'
line_batch_count = 50000 # tunable parameter
lines_seen = Set.new
line_number = 0
ARGF.each do |line|
   line_number += 1
   if (line_number % line_batch_count) == 0
     lines_seen.clear
   end
   unless lines_seen.include? line
      puts line
      lines_seen << line
   end
end

ধারণাটি হ্যাশ-সেটটি প্রায়শই ঘন ঘন পরিষ্কার করা। তারপরে এটি পুনরাবৃত্তি হয়:

$ cat uniqm-input.txt | ruby uniqm-capped.rb | wc -l
   20021

$ cat uniqm-input.txt | ruby uniqm-capped.rb | ruby uniqm-capped.rb | wc -l
    1001

$ cat uniqm-input.txt | ruby uniqm-capped.rb | ruby uniqm-capped.rb | head
1506
1054
1623
1002
1173
1400
1226
1340
1824
1091

সুতরাং আপনি এই আবদ্ধ সংস্করণটি বার বার চালনা করতে পারবেন, যতক্ষণ না লাইন-কাউন্টটি একটি পুনরাবৃত্তি থেকে অন্যটিতে পরিবর্তন না হয়।

নোট করুন যে এই ক্যাপড-ইউনিকম কৌশলটি ভাষা-স্বতন্ত্র: আপনি lines_seenপ্রতিটি এন লাইনে অ্যারে সাফ করতে পারেন যে আপনি awk, পাইথন, পারল, সি ++ ইত্যাদি ব্যবহার করছেন কিনা এই সমস্ত ভাষার জন্য নির্দিষ্ট-স্পষ্ট পদ্ধতি রয়েছে; আমি বিশ্বাস করি awkএর deleteঅ-মানক কিন্তু সাধারণ।

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