প্রথম কলামে awk বা সেড দ্বারা সংঘবদ্ধ লাইনগুলি


12

awkনিম্নলিখিত পরিস্থিতিতে আমি কীভাবে ব্যবহার করতে পারি ?

আমি একই কলাম দিয়ে শুরু হওয়া লাইনগুলিকে একত্রিত করতে চাই। পরে যোগ দেয় তাদের কেবলমাত্র প্রথম কলামে রাখা হয় (এই ক্ষেত্রে aaa, www, hhh)।

ফাইলটি স্পেস- বা ট্যাব-বিচ্ছিন্ন হতে পারে।

উদাহরণ ইনপুট:

aaa bbb ccc ddd NULL NULL NULL
aaa NULL NULL NULL NULL NULL NULL
aaa bbb ccc NULL NULL NULL NULL
www yyy hhh NULL NULL NULL NULL
hhh 111 333 yyy ooo hyy uuuioooy
hhh 111 333 yyy ooo hyy NULL

পছন্দসই আউটপুট:

aaa bbb ccc ddd NULL NULL NULL NULL NULL NULL NULL NULL NULL bbb ccc NULL NULL NULL NULL
www yyy hhh NULL NULL NULL NULL
hhh 111 333 yyy ooo hyy uuuioooy 111 333 yyy ooo hyy NULL

এর পটভূমি হ'ল আমি একটি খুব সাধারণ ফাইল-ভিত্তিক ডাটাবেস সেটআপ করতে চাই, যেখানে প্রথম কলামটি সর্বদা সত্তার সনাক্তকারী। একই সনাক্তকারী কলামের উপর ভিত্তি করে সমস্ত লাইন একত্রিত হয়।


1
যেখানে হয়নি uuuলাইন (আউটপুটে) থেকে আসা?
saeedn

দুঃখিত আমার খারাপ. আমি এটি সম্পাদনা করব।
ক্ষুদ্র

উত্তর:


8

জাজ ব্যবহার করে প্রতিটি লাইনে প্রথম কলামগুলি পেতে আপনি নিম্নলিখিতটি করতে পারেন:

< testfile awk '{print $1}'
aaa
aaa
aaa
www
hhh
hhh

বাকি লাইনের জন্য আপনার কীগুলি keys সুতরাং আপনি একটি হ্যাশ টেবিল তৈরি করতে পারেন, কী হিসাবে প্রথম স্তম্ভটি কী হিসাবে এবং লাইনের দ্বিতীয় কলামটি মান হিসাবে ব্যবহার করুন:

< testfile awk '{table[$1]=table[$1] $2;} END {for (key in table) print key " => " table[key];}'
www => yyy
aaa => bbbNULLbbb
hhh => 111111

সম্পূর্ণ কলাম 2 দিয়ে শুরু করে পুরো রেখাটি পেতে, আপনাকে সমস্ত কলাম সংগ্রহ করতে হবে:

< testfile awk '{line="";for (i = 2; i <= NF; i++) line = line $i " "; table[$1]=table[$1] line;} END {for (key in table) print key " => " table[key];}'
www => yyy hhh NULL NULL NULL NULL 
aaa => bbb ccc ddd NULL NULL NULL NULL NULL NULL NULL NULL NULL bbb ccc    NULL NULL NULL NULL 
hhh => 111 333 yyy ooo hyy uuuioooy 111 333 yyy ooo hyy NULL 

হাই, হ্যাঁ এটিতে হ্যাশ টেবিলগুলি ভেঙে ফেলার দরকার ছিল। ধন্যবাদ!
ক্ষুদ্র

2
@ টিনি - আমি ধরে নিছিলাম অর্ডারটি সংরক্ষণ করা দরকার। এটি কি নয় (এই উত্তরটি হ্যাশিং প্রক্রিয়া অনুসারে অর্ডার সরবরাহ করে, আপনার মূল আদেশটি নয়)?
ire_and_curses

3

অন্য কেউ উত্তেজনা বা খারাপভাবে উত্তর দিতে পারে তবে পাইথন সংস্করণটি সোজা এবং এটি আপনার পক্ষে সহায়ক হতে পারে।

#!/usr/bin/env python

input_file = 'input.dat'
in_fh      = open(input_file, 'r')

input_order = []
seen        = {}
for line in in_fh:    
    # Remove the newline character...
    line = line[:-1]

    # Separate the first column from the rest of the line...
    key_col, sep, rest_of_line = line.partition(" ")
    rest_of_line = sep + rest_of_line  

    # If we've seen this key already, concatenate the line...
    if key_col in seen:
        seen[key_col] += rest_of_line
    # ...otherwise, record the ordering, and store the new info
    else:
        input_order.append(key_col)
        seen[key_col] = rest_of_line

in_fh.close()

# Dump the ordered output to stdout
for unique_col in input_order:
    print unique_col + seen[unique_col]

খুব ঠান্ডা. আমার শূন্য অভিজ্ঞতা অজগর দিয়ে আমি এমনকি স্ক্রিপ্ট সম্পাদনা করতে পেরেছি যে এটি প্রথম যুক্তিটিকে ইনপুট ফাইলের নাম হিসাবে গ্রহণ করে :)
ক্ষুদ্র

2

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

touch outfile
while read; do
  join -a1 -a2 outfile <(echo $REPLY) > tmp
  mv tmp outfile
done < infile

এটির দক্ষতা উন্নত করতে সঞ্চয় outfileএবং tmpর‌্যামডিস্কে সহায়তা করতে পারে।

সম্পাদন করা

বা অস্থায়ী ফাইল ছাড়াই:

out=""
while read; do
  out=$(join -a1 -a2 <(echo -n "$out") <(echo -n "$REPLY"))
done < infile

echo "$out"

2

এবং এখানে একটি পার্ল ওয়ান-লাইনার রয়েছে:

$ perl -e 'my %h; while(<>){chomp; @a=split(/\s+/); $k=shift(@a); $h{$k}.=join(" ", @a) . " "; } map{$h{$_}=~s/\s*$//; print "$_ $h{$_}\n}keys(%hash);' infile
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.