বেসে দুটি অ্যারে ছেদ করা


12

আমার দু'টি অ্যারে রয়েছে:

A=(vol-175a3b54 vol-382c477b vol-8c027acf vol-93d6fed0 vol-71600106 vol-79f7970e vol-e3d6a894 vol-d9d6a8ae vol-8dbbc2fa vol-98c2bbef vol-ae7ed9e3 vol-5540e618 vol-9e3bbed3 vol-993bbed4 vol-a83bbee5 vol-ff52deb2)
B=(vol-175a3b54 vol-e38d0c94 vol-2a19386a vol-b846c5cf vol-98c2bbef vol-7320102b vol-8f6226cc vol-27991850 vol-71600106 vol-615e1222)

অ্যারেগুলি সাজানো হয় না এবং সম্ভবত ডুপ্লিকেট উপাদানও থাকতে পারে।

  1. আমি এই দুটি অ্যারের ছেদ তৈরি করতে এবং উপাদানগুলিকে অন্য অ্যারেতে সঞ্চয় করতে চাই। আমি যে কিভাবে করতে হবে?

  2. এছাড়াও, আমি কীভাবে বি তে উপস্থিত থাকে এবং ক তে পাওয়া যায় না সেগুলির তালিকা কীভাবে পাব?


2
এই ধরণের কাজের জন্য শেল নয়, একটি আসল প্রোগ্রামিং ভাষা ব্যবহার করুন।
স্টাফেন চেজেলাস

1
আপনার কি উপাদানগুলির ক্রম ধরে রাখতে হবে? যদি সেখানে সদৃশ উপাদান থাকে (যেমন এ এবং বি উভয়ই fooদু'বার থাকে ) তবে আপনার কি সেগুলি ফলাফলটিতে নকল করা দরকার?
গিলস 'দু: খিত হওয়া বন্ধ করুন'

উত্তর:


14

comm(1)এমন একটি সরঞ্জাম যা দুটি তালিকার তুলনা করে এবং আপনাকে দুটি তালিকার মধ্যে ছেদ বা পার্থক্য দিতে পারে। তালিকাগুলি বাছাই করা দরকার তবে এটি অর্জন করা সহজ।

জন্য উপযুক্ত একটি অনুসারে সাজানো তালিকা মধ্যে আপনার অ্যারে পেতে comm:

$ printf '%s\n' "${A[@]}" | LC_ALL=C sort

এটি অ্যারে A কে বাছাই তালিকায় পরিণত করবে। বি জন্য একই কাজ।

commচৌরাস্তাটি ফিরতে ব্যবহার করতে:

$ comm -1 -2 file1 file2

-1 -2 ফাইল 1 (এ) এর অনন্য এবং ফাইল 2 (বি) এর অনন্য এন্ট্রিগুলি সরিয়ে দিতে বলে - দুটির ছেদটি।

এটি ফাইল 2 (বি) এ রয়েছে তবে ফাইল 1 (এ) নয় তা ফিরিয়ে আনতে:

$ comm -1 -3 file1 file2

-1 -3 ফাইল 1-এ অনন্য এন্ট্রিগুলি মুছে ফেলতে বলে এবং উভয়ের পক্ষেই সাধারণ - কেবল ফাইল-এ অনন্যদের রেখে leaving

এতে দুটি পাইপলাইন খাওয়ানোর জন্য comm, "প্রক্রিয়া সাবস্টিটিউশন" বৈশিষ্ট্যটি ব্যবহার করুন bash:

$ comm -1 -2 <(pipeline1) <(pipeline2)

এটি একটি অ্যারেতে ক্যাপচার করতে:

$ C=($(command))

সবগুলোকে একত্রে রাখ:

# 1. Intersection
$ C=($(comm -12 <(printf '%s\n' "${A[@]}" | LC_ALL=C sort) <(printf '%s\n' "${B[@]}" | LC_ALL=C sort)))

# 2. B - A
$ D=($(comm -13 <(printf '%s\n' "${A[@]}" | LC_ALL=C sort) <(printf '%s\n' "${B[@]}" | LC_ALL=C sort)))

এটি কেবল তখনই কাজ করবে যদি আপনার মানগুলি না থাকে \n
ক্রিস ডাউন

@ ক্রিসডাউন: ঠিক আছে। আমি সর্বদা শেল স্ক্রিপ্টগুলি লেখার চেষ্টা করি যা সঠিকভাবে উদ্ধৃত হয় এবং সমস্ত অক্ষর পরিচালনা করে তবে আমি ছেড়ে দিয়েছি \ n। আমি এটি কখনও ফাইলের নামে দেখিনি এবং ইউনিক্স সরঞ্জামগুলির একটি বিশাল গোছা im n সীমিত রেকর্ডগুলির সাথে কাজ করে যা আপনি বৈধ চর হিসাবে handle n হ্যান্ডেল করার চেষ্টা করলে আপনি অনেক কিছু হারাবেন।
ক্যামহ

1
জিইউআই ফাইল ম্যানেজারগুলি অন্য কোনও জায়গা থেকে অনুলিপি করা ইনপুট ফাইলনামগুলি সঠিকভাবে স্যানিটাইজ করে না এমনটি ফাইলের নামগুলিতে আমি দেখেছি (এছাড়াও, ফাইলের নাম সম্পর্কে কেউ কিছু বলেনি)।
ক্রিস ডাউন

এটি রক্ষা করার জন্য \n:arr1=( one two three "four five\nsix\nseven" ); arr2=( ${arr1[@]:1} "four five\\nsix" ); n1=${#arr1[@]}; n2=${#arr2[@]}; arr=( ${arr1[@]/ /'-_-'} ${arr2[@]/ /'-_-'} ); arr=( $( echo "${arr[@]}"|tr '\t' '-t-'|tr '\n' '-n-'|tr '\r' '-r-' ) ); arr1=( ${arr[@]:0:${n1}} ); arr2=( ${arr[@]:${n1}:${n2}} ); unset arr; printf "%0.s-" {1..10}; printf '\n'; printf '{'; printf " \"%s\" " "${arr1[@]}"; printf '}\n'; printf "%0.s-" {1..10}; printf '\n'; printf '{'; printf " \"%s\" " "${arr2[@]}"; printf '}\n'; printf "%0.s-" {1..10}; printf '\n\n'; unset arr1; unset arr2
জেসন আর। মিক

এক সেট করা উচিত নয় LC_ALL=C। পরিবর্তে LC_COLLATE=Cঅন্যান্য পার্শ্ব প্রতিক্রিয়া ছাড়াই একই কর্মক্ষমতা লাভের জন্য সেট করুন । প্রাপ্ত করার জন্য সঠিক ফলাফল আপনার কাছে একই কোলেশন সেট করতে হবে commযে জন্য ব্যবহৃত হয় sort: যেমনunset LC_ALL; LC_COLLATE=C ; comm -12 <(printf '%s\n' "${A[@]}" | sort) <(printf '%s\n' "${B[@]}" | sort)
Sorpigal

4

আপনি উভয় অ্যারে দিয়ে লুপিং করে এবং তুলনা করে A এবং B উভয় উপাদানগুলিকেই পেতে পারেন:

A=(vol-175a3b54 vol-382c477b vol-8c027acf vol-93d6fed0 vol-71600106 vol-79f7970e vol-e3d6a894 vol-d9d6a8ae vol-8dbbc2fa vol-98c2bbef vol-ae7ed9e3 vol-5540e618 vol-9e3bbed3 vol-993bbed4 vol-a83bbee5 vol-ff52deb2)
B=(vol-175a3b54 vol-e38d0c94 vol-2a19386a vol-b846c5cf vol-98c2bbef vol-7320102b vol-8f6226cc vol-27991850 vol-71600106 vol-615e1222)

intersections=()

for item1 in "${A[@]}"; do
    for item2 in "${B[@]}"; do
        if [[ $item1 == "$item2" ]]; then
            intersections+=( "$item1" )
            break
        fi
    done
done

printf '%s\n' "${intersections[@]}"

আপনি বি তে সমস্ত উপাদান পেতে পারেন তবে এ তেমন পদ্ধতিতে পাবেন না:

A=(vol-175a3b54 vol-382c477b vol-8c027acf vol-93d6fed0 vol-71600106 vol-79f7970e vol-e3d6a894 vol-d9d6a8ae vol-8dbbc2fa vol-98c2bbef vol-ae7ed9e3 vol-5540e618 vol-9e3bbed3 vol-993bbed4 vol-a83bbee5 vol-ff52deb2)
B=(vol-175a3b54 vol-e38d0c94 vol-2a19386a vol-b846c5cf vol-98c2bbef vol-7320102b vol-8f6226cc vol-27991850 vol-71600106 vol-615e1222)

not_in_a=()

for item1 in "${B[@]}"; do
    for item2 in "${A[@]}"; do
        [[ $item1 == "$item2" ]] && continue 2
    done

    # If we reached here, nothing matched.
    not_in_a+=( "$item1" )
done

printf '%s\n' "${not_in_a[@]}"

অনুশীলন: আপনি যদি আদান-প্রদান করেন Aএবং B, পুনরায় intersectionsঅর্ডারিংয়ের ক্ষেত্রে সবসময় একই থাকে?
গিলস 'তাই খারাপ হওয়া বন্ধ করুন'

@ গিলস যদি অ্যারেতে সদৃশ উপাদান থাকতে পারে, না।
ক্রিস ডাউন

3

এটি করার জন্য বরং মার্জিত এবং দক্ষ পদ্ধতির ব্যবহার রয়েছে uniq- তবে, আমাদের কেবলমাত্র অনন্য আইটেম রেখে প্রতিটি অ্যারে থেকে নকলগুলি অপসারণ করতে হবে। আপনি যদি সদৃশগুলি সংরক্ষণ করতে চান তবে কেবলমাত্র একটি উপায় "উভয় অ্যারে লুপ করে এবং তুলনা করে"।

আমাদের দুটি অ্যারে বিবেচনা করুন:

A=(vol-175a3b54 vol-382c477b vol-8c027acf vol-93d6fed0 vol-71600106 vol-79f7970e vol-e3d6a894 vol-d9d6a8ae vol-8dbbc2fa vol-98c2bbef vol-ae7ed9e3 vol-5540e618 vol-9e3bbed3 vol-993bbed4 vol-a83bbee5 vol-ff52deb2)
B=(vol-175a3b54 vol-e38d0c94 vol-2a19386a vol-b846c5cf vol-98c2bbef vol-7320102b vol-8f6226cc vol-27991850 vol-71600106 vol-615e1222)

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

সুতরাং, আসুন রূপান্তর!

$ A=(echo ${A[@]} | sed 's/ /\n/g' | sort | uniq)
$ B=(echo ${B[@]} | sed 's/ /\n/g' | sort | uniq)
  1. অন্তর্ছেদ:

    $ echo ${A[@]} ${B[@]} | sed 's/ /\n/g' | sort | uniq -d

    যদি আপনি উপাদানগুলি অন্য অ্যারেতে সঞ্চয় করতে চান:

    $ intersection_set=$(echo ${A[@]} ${B[@]} | sed 's/ /\n/g' | sort | uniq -d)
    
    $ echo $intersection_set
    vol-175a3b54 vol-71600106 vol-98c2bbef

    uniq -dমানে কেবল ডুপ্লিকেটগুলি দেখান (আমি মনে করি, uniqএটির উপলব্ধির কারণে এটি দ্রুততর: আমি অনুমান করি যে এটি XORঅপারেশন দিয়ে সম্পন্ন হয়েছে )।

  2. উপস্থিত Bএবং পাওয়া যায় না এমন উপাদানগুলির তালিকা পান A, যেমনB\A

    $ echo ${A[@]} ${B[@]} | sed 's/ /\n/g' | sort | uniq -d | xargs echo ${B[@]} | sed 's/ /\n/g' | sort | uniq -u

    অথবা, একটি ভেরিয়েবলে সঞ্চয় সহ:

    $ subtraction_set=$(echo ${A[@]} ${B[@]} | sed 's/ /\n/g' | sort | uniq -d | xargs echo ${B[@]} | sed 's/ /\n/g' | sort | uniq -u)
    
    $ echo $subtraction_set
    vol-27991850 vol-2a19386a vol-615e1222 vol-7320102b vol-8f6226cc vol-b846c5cf vol-e38d0c94

    সুতরাং, প্রথমে আমরা ছেদ পেয়েছি Aএবং এটি B(যা কেবল তাদের মধ্যে নকলগুলির সেট), এটি বলুন A/\Bএবং তারপরে আমরা Bএবং A/\B(যা কেবলমাত্র অনন্য উপাদান) এর উল্টানো ছেদটি অপারেশন ব্যবহার করেছি , তাই আমরা পেয়েছি B\A = ! (B /\ (A/\B))

পিএস uniqলিখেছিলেন রিচার্ড এম স্টালম্যান এবং ডেভিড ম্যাকেনজি।


1

দক্ষতা উপেক্ষা, এখানে একটি পদ্ধতির:

declare -a intersect
declare -a b_only
for bvol in "${B[@]}"
do
    in_both=""
    for avol in "${A[@]}"
    do
        [ "$bvol" = "$avol" ] && in_both=Yes
    done
    if [ "$in_both" ]
    then
        intersect+=("$bvol")
    else
        b_only+=("$bvol")
    fi
done
echo "intersection=${intersect[*]}"
echo "In B only=${b_only[@]}"

0

আমার খাঁটি বাশ উপায়

এই ভেরিয়েবলগুলিতে কেবল vol-XXXযেখানে XXXহেক্সাডেসিমাল সংখ্যা রয়েছে তাই ব্যাশ অ্যারে ব্যবহারের দ্রুত উপায় রয়েছে a

unset A B a b c i                    # Only usefull for re-testing...

A=(vol-175a3b54 vol-382c477b vol-8c027acf vol-93d6fed0 vol-71600106 vol-79f7970e
   vol-e3d6a894 vol-d9d6a8ae vol-8dbbc2fa vol-98c2bbef vol-ae7ed9e3 vol-5540e618
   vol-9e3bbed3 vol-993bbed4 vol-a83bbee5 vol-ff52deb2)
B=(vol-175a3b54 vol-e38d0c94 vol-2a19386a vol-b846c5cf vol-98c2bbef vol-7320102b
   vol-8f6226cc vol-27991850 vol-71600106 vol-615e1222)

for i in ${A[@]#vol-};do
    [ "${a[$((16#$i))]}" ] && echo Duplicate vol-$i in A
    ((a[$((16#$i))]++))
    ((c[$((16#$i))]++))
  done
for i in ${B[@]#vol-};do
    [ "${b[$((16#$i))]}" ] && echo Duplicate vol-$i in B
    ((b[$((16#$i))]++))
    [ "${c[$((16#$i))]}" ] && echo Present in A and B: vol-$i
    ((c[$((16#$i))]++))
  done

এটি অবশ্যই আউটপুট:

Present in A and B vol-175a3b54
Present in A and B vol-98c2bbef
Present in A and B vol-71600106

এই অবস্থায়, আপনি বাশ পরিবেশের মধ্যে রয়েছে:

set | grep ^c=
c=([391789396]="2" [664344656]="1" [706295914]="1" [942425979]="1" [1430316568]="1"
[1633554978]="1" [1902117126]="2" [1931481131]="1" [2046269198]="1" [2348972751]="1"
[2377892602]="1" [2405574348]="1" [2480340688]="1" [2562898927]="2" [2570829524]="1"
[2654715603]="1" [2822487781]="1" [2927548899]="1" [3091645903]="1" [3654723758]="1"
[3817671828]="1" [3822495892]="1" [4283621042]="1")

সুতরাং আপনি করতে পারেন:

for i in ${!b[@]};do
    [ ${c[$i]} -eq 1 ] &&
        printf "Present only in B: vol-%8x\n" $i
  done

এটি রেন্ডার করবে:

Present only in B: vol-27991850
Present only in B: vol-2a19386a
Present only in B: vol-615e1222
Present only in B: vol-7320102b
Present only in B: vol-8f6226cc
Present only in B: vol-b846c5cf
Present only in B: vol-e38d0c94

তবে এই সংখ্যাটি বাছাই করা হয়! আপনি যদি মূল ক্রম চান তবে আপনি এটি করতে পারেন:

for i in ${B[@]#vol-};do
    [ ${c[((16#$i))]} -eq 1 ] && printf "Present in B only: vol-%s\n" $i
  done

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

Present in B only: vol-e38d0c94
Present in B only: vol-2a19386a
Present in B only: vol-b846c5cf
Present in B only: vol-7320102b
Present in B only: vol-8f6226cc
Present in B only: vol-27991850
Present in B only: vol-615e1222

অথবা

for i in ${!a[@]};do
    [ ${c[$i]} -eq 1 ] && printf "Present only in A: vol-%8x\n" $i
  done

শুধুমাত্র এ তে দেখানোর জন্য :

Present only in A: vol-382c477b
Present only in A: vol-5540e618
Present only in A: vol-79f7970e
Present only in A: vol-8c027acf
Present only in A: vol-8dbbc2fa
Present only in A: vol-93d6fed0
Present only in A: vol-993bbed4
Present only in A: vol-9e3bbed3
Present only in A: vol-a83bbee5
Present only in A: vol-ae7ed9e3
Present only in A: vol-d9d6a8ae
Present only in A: vol-e3d6a894
Present only in A: vol-ff52deb2

অথবা এমনকি:

for i in ${!b[@]};do
    [ ${c[$i]} -eq 2 ] && printf "Present in both A and B: vol-%8x\n" $i
  done

হবে পুনরায় মুদ্রণ :

Present in both A and B: vol-175a3b54
Present in both A and B: vol-71600106
Present in both A and B: vol-98c2bbef

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