নেস্টেড লুপগুলি সহ একটি শেল স্ক্রিপ্ট থেকে প্রস্থান করা হচ্ছে


11

নেস্টেড লুপগুলির সাথে আমার একটি শেল স্ক্রিপ্ট রয়েছে এবং সবেমাত্র জানতে পেরেছি যে "প্রস্থান" আসলে স্ক্রিপ্ট থেকে প্রস্থান করে না, কেবলমাত্র বর্তমান লুপ। কোনও নির্দিষ্ট ত্রুটির শর্তে স্ক্রিপ্টটি পুরোপুরি প্রস্থান করার অন্য কোনও উপায় আছে কি?

আমি "সেট-ই" ব্যবহার করতে চাই না, কারণ গ্রহণযোগ্য ত্রুটি রয়েছে এবং এটির জন্য খুব বেশি নতুন করে লেখা দরকার।

এই মুহুর্তে, আমি প্রক্রিয়াটিকে ম্যানুয়ালি মেরে ফেলতে ব্যবহার করছি, তবে মনে হয় এটি করার আরও ভাল উপায় হওয়া উচিত।


1
আপনি কী বলতে চাইছেন যে "প্রস্থান" আসলে স্ক্রিপ্ট থেকে প্রস্থান করে না? এটি, চেষ্টা করুন bash -c 'for x in y z; do exit; done; echo "This never gets printed"'
ক্রিস ডাউন

আপনি ঠিক বলেছেন, এটি সাধারণত নেস্টেড লুপগুলির বাইরে বেরিয়ে আসা উচিত, তবে আমি যখন প্রস্থানটি ব্যবহার করি তখন আমার স্ক্রিপ্টটি বাইরের লুপ দিয়ে চালিয়ে যায়। আমি স্ক্রিপ্ট পোস্ট করতে পারি না।
ব্যবহারকারী923487

2
আপনি কেন এমন স্ক্রিপ্ট লিখতে পারবেন না যা সমস্যাটি দেখায় এবং এটি এখানে পোস্ট করতে পারে? এটা আমার কাছে অসম্ভব মনে হচ্ছে।
টবি স্পিড

1
আপনার কোডের অভ্যন্তরীণ লুপটি একটি সাব-শেলটিতে স্থান নেয়?
টবি স্পিড

@ টবি বেশিরভাগ স্ক্রিপ্ট লগিংয়ের উদ্দেশ্যে একটি সাব শেলের মধ্যে রয়েছে, তবে উভয় লুপ এবং বাকী কোড একই সাব শেলের মধ্যে রয়েছে।
ব্যবহারকারী 923487

উত্তর:


19

আপনার সমস্যা নেস্ট লুপ নয়, প্রতি সে। এটি এমন যে আপনার এক বা একাধিক অভ্যন্তরীণ লুপগুলি সাব-শেলের মধ্যে চলছে

এইটা কাজ করে:

#!/bin/bash

for i in $(seq 1 100); do
        echo i $i
        for j in $(seq 1 10) ; do
                echo j $j
                sleep 1
                [[ $j = 3 ]] && { echo "I've had enough!" 1>&2; exit 1; }
        done
        echo "After the j loop."
done
echo "After all the loops."

আউটপুট:

i 1
j 1
j 2
j 3
I've had enough!

এটি আপনার বর্ণিত সমস্যাটি উপস্থাপন করে:

#!/bin/bash

for i in $(seq 1 100); do
        echo i $i
        cat /etc/passwd | while read line; do
                echo LINE $line
                sleep 1
                [[ "$line" = "daemon:x:2:2:daemon:/sbin:/sbin/nologin" ]] && { echo "I've had enough!" 1>&2; exit 1; }
        done
        echo "After the j loop."
done    
echo "After all the loops."

আউটপুট:

i 1
LINE root:x:0:0:root:/root:/bin/bash
LINE bin:x:1:1:bin:/bin:/sbin/nologin
LINE daemon:x:2:2:daemon:/sbin:/sbin/nologin
I've had enough!
After the j loop.
i 2
LINE root:x:0:0:root:/root:/bin/bash
LINE bin:x:1:1:bin:/bin:/sbin/nologin
LINE daemon:x:2:2:daemon:/sbin:/sbin/nologin
I've had enough!
After the j loop.
i 3
LINE root:x:0:0:root:/root:/bin/bash
(...etc...)

সমাধান এখানে; আপনাকে সাব-শেলগুলিতে চলমান অভ্যন্তরীণ লুপগুলির রিটার্ন মানটি পরীক্ষা করতে হবে:

#!/bin/bash

for i in $(seq 1 100); do
        echo i $i
        cat /etc/passwd | while read line; do
                echo LINE $line
                sleep 1
                [[ "$line" = "daemon:x:2:2:daemon:/sbin:/sbin/nologin" ]] && { echo "I've had enough!" 1>&2; exit 1; }
        done
        err=$?; [[ $err != 0 ]] && exit $err
        echo "After the j loop."
done
echo "After all the loops."

পরীক্ষা নোট করুন: [[ $? != 0 ]] && exit $?

আউটপুট:

i 1
LINE root:x:0:0:root:/root:/bin/bash
LINE bin:x:1:1:bin:/bin:/sbin/nologin
LINE daemon:x:2:2:daemon:/sbin:/sbin/nologin
I've had enough!

সম্পাদনা করুন: আপনি কী সাবচেলে রয়েছেন তা যাচাই করতে, আপনার বর্তমান শেলের প্রসেস আইডি কী তা জানাতে "উত্তর" স্ক্রিপ্টটি সংশোধন করুন। দ্রষ্টব্য: এটি কেবল ব্যাশে 4 এ কাজ করে:

#!/bin/bash

for i in $(seq 1 100); do
        echo pid $BASHPID i $i
        cat /etc/passwd | while read line; do
                echo pid $BASHPID LINE $line
                sleep 1
                [[ "$line" = "daemon:x:2:2:daemon:/sbin:/sbin/nologin" ]] && { echo "I've had enough!" 1>&2; exit 1; }
        done
        err=$?; [[ $err != 0 ]] && echo pid $BASHPID && exit $err
        echo "After the j loop."
done
echo "After all the loops."

আউটপুট:

pid 31793 i 1
pid 31796 LINE root:x:0:0:root:/root:/bin/bash
pid 31796 LINE bin:x:1:1:bin:/bin:/sbin/nologin
pid 31796 LINE daemon:x:2:2:daemon:/sbin:/sbin/nologin
I've had enough!
pid 31793

"আই" এবং "জে" ভেরিয়েবলগুলি আপনার জন্য ফোর্টরানের সৌজন্যে এনেছে। আপনার দিনটি শুভ হোক. :-)


অভ্যন্তরীণ এবং বাইরের উভয় লুপ একই সাব শেলের মধ্যে চলছে, সুতরাং অভ্যন্তরীণ প্রস্থান করে উভয় প্রস্থান করা উচিত? সমস্যাটি নিজেই আবার প্রজনন করতে আমার সমস্যা হচ্ছে। যত তাড়াতাড়ি আমি প্রোগ্রামের বেশিরভাগ যুক্তি সরিয়ে নিই, সমস্যাটি চলে গেছে। যাইহোক, আমি এটি আপাতত উত্তর হিসাবে চিহ্নিত করব, কারণ এটি এটি দিয়ে কিছু করার সম্ভবত রয়েছে।
ব্যবহারকারী 923487

আপনার সরবরাহিত লিঙ্কটি পড়ার পরে, আমি মনে করি যে আমি সমস্যাটি পেয়েছি। বাইরের লুপটিতে আমি "বিড়াল ফাইল | পাঠের লাইনের সময়" করছি। পাইপিং একটি উপ শেল তৈরি করে। আমি এটা জানতাম না।
ব্যবহারকারী 923487

@ ব্যবহারকারী923487 - আমার আপডেট হওয়া উত্তরটি দেখুন। আপনার যদি বাশ 4 থাকে তবে আপনি সাব-শেল পিড প্রতিধ্বনি করতে পারেন (বা প্রিন্টফ, যদি আপনি আধুনিক হন) এবং আপনি সাব-শেলের মধ্যে আছেন কিনা তা যাচাই করতে পারেন। আপনার বাশ সংস্করণ দেখতে bash --versionকমান্ড লাইনে টাইপ করুন।
মাইক এস

খুব উপকারী. ধন্যবাদ! যদিও আমি "কিল্ল স্ক্রিপ্টনাম.শ" বলতে পারি এটি সমাধানের সবচেয়ে সহজ উপায় বলে মনে হচ্ছে।
ব্যবহারকারী 923487

2

পূর্বের উত্তরটি ব্যবহার করে [[ $? != 0 ]] && exit $?তবে এটি প্রত্যাশিত হিসাবে যথেষ্ট কাজ করবে না বলে [[ $? != 0 ]]পরীক্ষাটি $?আবারো শূন্যে ফিরে আসবে, যার অর্থ স্ক্রিপ্টটি প্রত্যাশার সাথে সাথে প্রারম্ভিকভাবে প্রস্থান করলেও এটি সর্বদা কোড 0 দিয়ে বেরিয়ে আসবে (প্রত্যাশিত নয়) । এছাড়াও, স্ট্রিং তুলনা পরীক্ষার -neচেয়ে সংখ্যা তুলনা পরীক্ষাটি ব্যবহার করা ভাল !=। সুতরাং আইএমএইচও একটি আরও ভাল সমাধান ব্যবহার করা হয়:

err=$?; [[ $err -ne 0 ]] && exit $err

যেহেতু এটি নিশ্চিত করবে যে আসল প্রস্থান কোডটি সঠিকভাবে সেট করা আছে।


ভাল মতামত। আমি কোড সংশোধন করেছি।
মাইক এস

1

আপনি ব্যবহার করতে পারেন break

থেকে help break:

Exit a FOR, WHILE or UNTIL loop.  If N is specified, break N enclosing loops.

সুতরাং তিনটি এনকোলেজিং লুপগুলি থেকে বেরিয়ে আসার জন্য যদি আপনার প্রধান একের ভিতরে দুটি নেস্ট লুপ থাকে তবে সেগুলি থেকে প্রস্থান করার জন্য এটি ব্যবহার করুন:

break 3

লুপগুলির পরে আরও কোড রয়েছে, সুতরাং কেবল তাদের মধ্যেই ব্রেক করা যথেষ্ট নয়।
ব্যবহারকারী 923487

1
ঠাণ্ডা THX! উদাহরণস্বরূপfor((i=0;i<3;i++));do echo A;for((j=0;j<2;j++));do echo B;break 2;done;done
অ্যাকোরিয়াস পাওয়ার

0

exit পুরো শেল বা বর্তমান উপ-শেলটি সমাপ্ত করে:

$ bash -c 'for i in 1 2 3; do for j in 4 5 6; do echo $i; exit 1; echo $j; done; done'
1
$ echo $?
1
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.