লুপগুলির জন্য বহুগুণযোগ্য


12

forলুপ ইনগুলিতে একাধিক ভেরিয়েবল (কেবল পূর্ণসংখ্যা নয়) নির্দিষ্ট করার কোনও উপায় আছে কি bash? আমার কাছে 2 টি ফাইল থাকতে পারে যথেচ্ছ পাঠ্য যার সাথে আমার কাজ করা দরকার।

আমার কার্যত যা প্রয়োজন তা হ'ল এইরকম:

for i in $(cat file1) and j in $(cat file2); do command $i $j; done

কোন ধারনা?

উত্তর:


11

প্রথমত, এর জন্য লাইনগুলি পড়বেন না , কারণ শব্দ বিভক্তকরণের মাধ্যমে পঠন লাইনের সাথে বেশ কয়েকটি অনিবার্য সমস্যা রয়েছে।

সমান দৈর্ঘ্যের ফাইলগুলি ধরে নেওয়া, বা আপনি যদি দুটি ফাইলের সংক্ষিপ্ত বিবরণ না পড়েন কেবল লুপ করতে চান তবে একটি সহজ সমাধান সম্ভব।

while read -r x && read -r y <&3; do
    ...
done <file1 3<file2

readপ্রত্যাবর্তন কখন মিথ্যা এবং অন্যান্য বেশ কয়েকটি কারণে আরও সাধারণ সমাধান একসাথে রাখা শক্ত । এই উদাহরণটি স্বেচ্ছাসেবী সংখ্যক স্ট্রিম পড়তে পারে এবং সংক্ষিপ্ততম বা দীর্ঘতম ইনপুট পরে ফিরে আসতে পারে।

#!/usr/bin/env bash

# Open the given files and assign the resulting FDs to arrName.
# openFDs arrname file1 [file2 ...]
openFDs() {
    local x y i arr=$1

    [[ -v $arr ]] || return 1
    shift

    for x; do
        { exec {y}<"$x"; } 2>/dev/null || return 1
        printf -v "${arr}[i++]" %d "$y"
    done
}

# closeFDs FD1 [FD2 ...]
closeFDs() {
    local x
    for x; do
        exec {x}<&-
    done
}

# Read one line from each of the given FDs and assign the output to arrName.
# If the first argument is -l, returns false only when all FDs reach EOF.
# readN [ -l ] arrName FD1 [FD2 ...]
readN() {
    if [[ $1 == -l ]]; then
        local longest
        shift
    else
        local longest=
    fi

    local i x y status arr=$1
    [[ -v $arr ]] || return 1
    shift

    for x; do
        if IFS= read -ru "$x" "${arr}[i]" || { unset -v "${arr}[i]"; [[ ${longest+_} ]] && return 1; }; then
            status=0
        fi
        ((i++))
    done
    return ${status:-1}
}

# readLines file1 [file2 ...]
readLines() {
    local -a fds lines
    trap 'closeFDs "${fds[@]}"' RETURN
    openFDs fds "$@" || return 1

    while readN -l lines "${fds[@]}"; do
        printf '%-1s ' "${lines[@]}"
        echo
    done
}

{
    readLines /dev/fd/{3..6} || { echo 'error occured' >&2; exit 1; }
} <<<$'a\nb\nc\nd' 3<&0 <<<$'1\n2\n3\n4\n5' 4<&0 <<<$'x\ny\nz' 5<&0 <<<$'7\n8\n9\n10\n11\n12' 6<&0

# vim: set fenc=utf-8 ff=unix ts=4 sts=4 sw=4 ft=sh nowrap et:

সুতরাং readNপায় কিনা তার উপর নির্ভর করে -lআউটপুট হয়

a 1 x 7
b 2 y 8
c 3 z 9
d 4 10
5 11
12

অথবা

a 1 x 7
b 2 y 8
c 3 z 9

একাধিক অ্যারেগুলিতে সমস্ত কিছু সংরক্ষণ না করে একটি লুপে একাধিক স্ট্রিম পড়ার বিষয়গুলি সাধারণ isn't আপনি যদি কেবল অ্যারেগুলি পড়তে চান তবে আপনার উচিত mapfile


||আমার জন্য কাজ করে না। এটি প্রক্রিয়া file1 তারপর file2 , কিন্তু এটা সাথে সিংক্রোনাইজ ফাইল রাখে &&, যা থেকে প্রস্থান করার সময় প্রথম উপর লুপ ফাইলের শেষে । - জিএনইউ বাশ 4.1.5
পিটার.ও

পরীক্ষার জন্য আমার কাছে মুক্ত মুহূর্ত ছিল না - হ্যাঁ আপনি সম্ভবত পুনরাবৃত্তির জন্য দুটি উপাদানই চাইবেন। ||"তালিকা" অপারেটর সবচেয়ে ভাষায় মত স্বল্প-পরিক্রমার করা হয়। অবশ্যই এর আগে হাজার বার উত্তর দেওয়া হয়েছে ...
ormaaj

বিন্দুটি কতবার আগে কতবার উল্লেখ করা হয়েছিল তার ফ্রিকোয়েন্সি নয়। বরং এটি বর্তমানে আপনার উত্তরটিতে যে কোডটি প্রদর্শিত হচ্ছে তা কার্যকর হয় না । আপনার " সম্ভবত উভয় উপাদানই চান .." এর উপর ভিত্তি করে মনে হচ্ছে আপনি এখনও এটি পরীক্ষা করেন নি।
পিটার.ও

@ পিটার.ও আমি সচেতন এটা ঠিক করা হয়েছে।
ormaaj

2

Do-সম্পন্ন; সম্পন্ন - আপনার দুটি ফোর এবং দুটি ডোনের দরকার:

for i in $(< file1); do for j in $(< file2); do echo $i $j;done ; done

ফাইল 2 অবশ্যই অবশ্যই ফাইল 1-এ প্রতিটি শব্দের জন্য একবার প্রক্রিয়া করা হয়।

বিড়ালের পরিবর্তে <ব্যবহার করা বেশিরভাগ ক্ষেত্রেই অবিস্মরণীয় পারফরম্যান্স লাভ হওয়া উচিত। জড়িত কোনও উপপ্রসেস নেই। (শেষ বাক্য সম্পর্কে অনিশ্চিত)।

uncompressed:

for i in $(< file1)
do
  for j in $(< file2)
  do
    echo $i $j
  done
done

আপনি যদি শব্দগুলি পড়তে পছন্দ করেন না তবে লাইনগুলি এবং শ্বেত স্পেস সংরক্ষণ করে রাখার সময় ব্যবহার করুন এবং পড়ুন:

while read line; do while read second; do echo "${line}${second}"; done <file2 ; done <file1

আপনি যদি 2 টি ফাইল সংযোজন করতে চান এবং সেগুলি নীড় না করে:

cat file1 file2 | while read line; do echo "${line}"; done

আপনি যদি 2 টি ফাইল জিপ করতে চান তবে পেস্টটি ব্যবহার করুন:

paste file1 file2

1
আপনি বলছেন কোনও উপ-প্রসেস চালিত নেই। () একটি সাবশেল নয়? আমি দুল হতে চাই না তবে আমি এখন নিশ্চিত যা জানি না। উদাহরণস্বরূপ আমি জানি যে যখন আমার একটি স্ক্রিপ্ট আছে এবং আমি চাই না যে এটি বর্তমান শেলটিকে সিডির সাহায্যে কলুষিত করে, আমি এটি একটি () এর মধ্যে করি। এছাড়াও চলমান (ঘুম 4) এবং উদাহরণস্বরূপ একটি পিএস অনুসরণ করে আমাকে দেখায় যে প্রক্রিয়াটি এখনও চলছে। আপনি দয়া করে বিস্তারিত বলতে পারেন।
সিলভাররোকার

ভাল - আমি দুঃখিত, আমি এখানে মৌলিক ব্যতিরেকে অভিনয় করছি। আমি ভেবেছিলাম আমি এটি শুনেছি, তবে সম্ভবত এটি কেবল <তুলনা করে cat। এবং আমি কীভাবে এটি পরীক্ষা করব এবং কখন এটি শব্দার্থগতভাবে গুরুত্বপূর্ণ হয়ে উঠব তা সম্পর্কে আমি নিশ্চিত নই। যদি পাইপগুলি আহ্বান করা হয় তবে উপ-প্রক্রিয়াগুলিতে ভেরিয়েবলগুলি মূল প্রক্রিয়াটিতে বুদবুদ না করে তবে আমাদের এখানে ভেরিয়েবল নেই। আমি সমালোচনামূলক বাক্যটি দিয়েছি, যতক্ষণ না কেউ এটি ব্যাখ্যা করতে পারে।
ব্যবহারকারী অজানা

0

whileএকটি interesitng বাক্য গঠন আছে। আপনি do ... whileলুপের আগে একাধিক কমান্ড রাখতে পারেন , এবং আপনার বিশেষ প্রয়োজনীয়তার উপর নির্ভর করে প্রশ্নে কেসটিকে এই বৈশিষ্ট্যটি জাগ্রত করতে হবে: আপনি দীর্ঘতম ফাইলটি শেষ করতে বা কেবল সংক্ষিপ্ততম প্রান্তে পড়তে পারেন?

উদাহরণস্বরূপ, read || readসহজভাবে কাজ করে না (প্রশ্নের প্রয়োজনীয়তা অনুসারে), কারণ প্রথম ফাইলটির পড়া যখন হয় true, প্রথম ফাইলটি পড়া শুরু থেকে শেষ না হওয়া অবধি দ্বিতীয় ফাইলের পড়া বাদ দেওয়া হয় ... তারপরে, কারণ স্থিতি এখনও আছে true, যখন লুপটি অবিরত থাকে এবং দ্বিতীয় ফাইলটি শুরু থেকে শেষ পর্যন্ত পড়ে।

read && readআপনি যদি সংক্ষিপ্ততম ফাইল হিসাবে কেবলমাত্র পড়তে চান তবে ফাইলগুলি একযোগে (সমকালীনভাবে) পড়বে। তবে আপনি যদি উভয় ফাইলই এখানে পড়তে চান eofতবে আপনাকে while'sসিনট্যাক্স প্রয়োজনীয়তাগুলি নিয়ে কাজ করতে হবে, যেমন। হুকুমে অবিলম্বে সামনেdo while একটি নন-জিরো রিটার্ন কোড উত্পাদক লুপ যখন লুপ আউট বিরতি।

এখানে কিভাবে উভয় ফাইলগুলি পড়তে একটি উদাহরণ ফাইলের শেষে

while IFS= read -r line3 <&3 || ((eof3=1))
      IFS= read -r line4 <&4 || ((eof4=1))
      !((eof3 & eof4))
do
    echo "$line3, $line4"
done 3<file3 4<file4

(আপনি পড়ার আগে eof3 এবং eof4 পরীক্ষা করতে চাইতে পারেন, তবে সাধারণ ধারণাটি বিশেষত চূড়ান্ত সত্য / মিথ্যা অবস্থায় রয়েছে।

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