নীচে স্ক্রিপ্টের উদাহরণ দেওয়া আছে যা try/catch/finally
ব্যাশে প্রয়োগ করে।
এই প্রশ্নের অন্যান্য উত্তরের মতো, সাব-প্রসেসটি থেকে বেরিয়ে আসার পরে ব্যতিক্রম অবশ্যই ধরা উচিত।
উদাহরণস্বরূপ স্ক্রিপ্টগুলি একটি বেনামে ফিফো তৈরির মাধ্যমে শুরু হয়, যা স্ট্রিং বার্তাগুলি পাসের নিকটবর্তী ব্লকের শেষে command exception
বা পাস করতে ব্যবহৃত হয় । এখানে বার্তাগুলি ফিফো থেকে সরিয়ে একটি অ্যারে ভেরিয়েবলে রাখা হয়েছে। স্থিতিটি ফেরত আসে এবং আদেশগুলি দিয়ে যায় এবং একটি ভিন্ন ভেরিয়েবলে স্থাপন করা হয়। কোনও ব্লকে প্রবেশ করতে , এই স্থিতিটি শূন্য হওয়া উচিত নয়। একটি ব্লকে প্রবেশের অন্যান্য প্রয়োজনীয়তাগুলি পরামিতি হিসাবে পাস করা হয়। যদি কোনও ব্লকের শেষে পৌঁছে যায়, তবে স্থিতিটি শূন্যে সেট করা আছে। যদি ব্লকের সমাপ্তি পৌঁছে যায় এবং স্থিতিটি এখনও ননজারো হয়, তবে বার্তাগুলি এবং স্থিতি সহ একটি অন্তর্ভুক্ত নিক্ষেপ কার্যকর করা হবে। স্ক্রিপ্টটির জন্য ফাংশনটির কলিং দরকার যা একটি অবিবাহিত ব্যতিক্রম হ্যান্ডলার রয়েছে।throw
try
return
exit
catch
catch
catch
finally
trycatchfinally
trycatchfinally
কমান্ডের জন্য সিনট্যাক্সটি নীচে দেওয়া হয়েছে।
trycatchfinally [-cde] [-h ERR_handler] [-k] [-o debug_file] [-u unhandled_handler] [-v variable] fifo function
-c
বিকল্প ব্যতিক্রম বার্তা থেকে কল স্ট্যাক যোগ করা হয়েছে। বিকল্প ডিবাগ আউটপুট দেয়। বিকল্প কমান্ড ব্যতিক্রম দেয়। বিকল্প ব্যবহারকারী তাদের নিজের কমান্ড ব্যতিক্রম হ্যান্ডলার প্রতিস্থাপন করতে পারবেন। বিকল্প ডিবাগ আউটপুট কল স্ট্যাক যোগ করা হয়েছে। বিকল্পটি ডিফল্টরূপে আউটপুট ফাইল যা প্রতিস্থাপন । বিকল্প ব্যবহারকারী তাদের নিজের Unhandled ব্যতিক্রম হ্যান্ডলার প্রতিস্থাপন করতে পারবেন। বিকল্প যদিও কমান্ড উপকল্পন ব্যবহার মান ফিরে পাস বিকল্প ব্যবহারকারী পারেন।
এই ফিফো ফাইল নাম।
ফাংশনটি একটি সাবপ্রসেস হিসাবে ডাকা হয় ।
-d
-e
-h
-k
-o
/dev/fd/2
-u
-v
fifo
function
trycatchfinally
দ্রষ্টব্য: cdko
স্ক্রিপ্টটি সহজ করার জন্য বিকল্পগুলি সরানো হয়েছে।
catch
কমান্ডের জন্য সিনট্যাক্সটি নীচে দেওয়া হয়েছে।
catch [[-enoprt] list ...] ...
বিকল্পগুলি নীচে সংজ্ঞায়িত করা হয়েছে। প্রথম তালিকার মান হ'ল স্থিতি। পরবর্তী মান হ'ল বার্তা। যদি তালিকার চেয়ে আরও বার্তা থাকে তবে অবশিষ্ট বার্তাগুলি উপেক্ষা করা হবে।
-e
মানে [[ $value == "$string" ]]
(মান তালিকায় অন্তত একটি স্ট্রিং মেলে আছে)
-n
মানে [[ $value != "$string" ]]
(মান তালিকায় স্ট্রিং কোনো মিল পাওয়া যায়নি পারে)
-o
মানে [[ $value != $pattern ]]
(মান তালিকায় প্যাটার্নের কোনো মিল পাওয়া যায়নি পারে)
-p
মানে [[ $value == $pattern ]]
(মূল্য আছে তালিকার অন্তত একটি প্যাটার্নের সাথে মেলে)
-r
অর্থ [[ $value =~ $regex ]]
( তালিকার অন্তত একটি বর্ধিত নিয়মিত প্রকাশের সাথে মানটি মিলতে হবে ) এর
-t
অর্থ [[ ! $value =~ $regex ]]
(তালিকার মান বর্ধিত নিয়মিত প্রকাশের কোনওটির সাথে মেলে না)
try/catch/finally
স্ক্রিপ্ট নিচে দেওয়া হয়। এই উত্তরের জন্য স্ক্রিপ্টটি সরল করতে, বেশিরভাগ ত্রুটি পরীক্ষা করা সরানো হয়েছিল। এটি 64% দ্বারা আকার হ্রাস করেছে। এই লিপির সম্পূর্ণ অনুলিপি আমার অন্য উত্তরে পাওয়া যাবে ।
shopt -s expand_aliases
alias try='{ common.Try'
alias yrt='EchoExitStatus; common.yrT; }'
alias catch='{ while common.Catch'
alias hctac='common.hctaC; done; }'
alias finally='{ common.Finally'
alias yllanif='common.yllaniF; }'
DefaultErrHandler() {
echo "Orginal Status: $common_status"
echo "Exception Type: ERR"
}
exception() {
let "common_status = 10#$1"
shift
common_messages=()
for message in "$@"; do
common_messages+=("$message")
done
}
throw() {
local "message"
if [[ $# -gt 0 ]]; then
let "common_status = 10#$1"
shift
for message in "$@"; do
echo "$message" >"$common_fifo"
done
elif [[ ${#common_messages[@]} -gt 0 ]]; then
for message in "${common_messages[@]}"; do
echo "$message" >"$common_fifo"
done
fi
chmod "0400" "$common_fifo"
exit "$common_status"
}
common.ErrHandler() {
common_status=$?
trap ERR
if [[ -w "$common_fifo" ]]; then
if [[ $common_options != *e* ]]; then
common_status="0"
return
fi
eval "${common_errHandler:-} \"${BASH_LINENO[0]}\" \"${BASH_SOURCE[1]}\" \"${FUNCNAME[1]}\" >$common_fifo <$common_fifo"
chmod "0400" "$common_fifo"
fi
if [[ common_trySubshell -eq BASH_SUBSHELL ]]; then
return
else
exit "$common_status"
fi
}
common.Try() {
common_status="0"
common_subshell="$common_trySubshell"
common_trySubshell="$BASH_SUBSHELL"
common_messages=()
}
common.yrT() {
local "status=$?"
if [[ common_status -ne 0 ]]; then
local "message=" "eof=TRY_CATCH_FINALLY_END_OF_MESSAGES_$RANDOM"
chmod "0600" "$common_fifo"
echo "$eof" >"$common_fifo"
common_messages=()
while read "message"; do
[[ $message != *$eof ]] || break
common_messages+=("$message")
done <"$common_fifo"
fi
common_trySubshell="$common_subshell"
}
common.Catch() {
[[ common_status -ne 0 ]] || return "1"
local "parameter" "pattern" "value"
local "toggle=true" "compare=p" "options=$-"
local -i "i=-1" "status=0"
set -f
for parameter in "$@"; do
if "$toggle"; then
toggle="false"
if [[ $parameter =~ ^-[notepr]$ ]]; then
compare="${parameter#-}"
continue
fi
fi
toggle="true"
while "true"; do
eval local "patterns=($parameter)"
if [[ ${#patterns[@]} -gt 0 ]]; then
for pattern in "${patterns[@]}"; do
[[ i -lt ${#common_messages[@]} ]] || break
if [[ i -lt 0 ]]; then
value="$common_status"
else
value="${common_messages[i]}"
fi
case $compare in
[ne]) [[ ! $value == "$pattern" ]] || break 2;;
[op]) [[ ! $value == $pattern ]] || break 2;;
[tr]) [[ ! $value =~ $pattern ]] || break 2;;
esac
done
fi
if [[ $compare == [not] ]]; then
let "++i,1"
continue 2
else
status="1"
break 2
fi
done
if [[ $compare == [not] ]]; then
status="1"
break
else
let "++i,1"
fi
done
[[ $options == *f* ]] || set +f
return "$status"
}
common.hctaC() {
common_status="0"
}
common.Finally() {
:
}
common.yllaniF() {
[[ common_status -eq 0 ]] || throw
}
caught() {
[[ common_status -eq 0 ]] || return 1
}
EchoExitStatus() {
return "${1:-$?}"
}
EnableThrowOnError() {
[[ $common_options == *e* ]] || common_options+="e"
}
DisableThrowOnError() {
common_options="${common_options/e}"
}
GetStatus() {
echo "$common_status"
}
SetStatus() {
let "common_status = 10#$1"
}
GetMessage() {
echo "${common_messages[$1]}"
}
MessageCount() {
echo "${#common_messages[@]}"
}
CopyMessages() {
if [[ ${#common_messages} -gt 0 ]]; then
eval "$1=(\"\${common_messages[@]}\")"
else
eval "$1=()"
fi
}
common.GetOptions() {
local "opt"
let "OPTIND = 1"
let "OPTERR = 0"
while getopts ":cdeh:ko:u:v:" opt "$@"; do
case $opt in
e) [[ $common_options == *e* ]] || common_options+="e";;
h) common_errHandler="$OPTARG";;
u) common_unhandled="$OPTARG";;
v) common_command="$OPTARG";;
esac
done
shift "$((OPTIND - 1))"
common_fifo="$1"
shift
common_function="$1"
chmod "0600" "$common_fifo"
}
DefaultUnhandled() {
local -i "i"
echo "-------------------------------------------------"
echo "TryCatchFinally: Unhandeled exception occurred"
echo "Status: $(GetStatus)"
echo "Messages:"
for ((i=0; i<$(MessageCount); i++)); do
echo "$(GetMessage "$i")"
done
echo "-------------------------------------------------"
}
TryCatchFinally() {
local "common_errHandler=DefaultErrHandler"
local "common_unhandled=DefaultUnhandled"
local "common_options="
local "common_fifo="
local "common_function="
local "common_flags=$-"
local "common_trySubshell=-1"
local "common_subshell"
local "common_status=0"
local "common_command="
local "common_messages=()"
local "common_handler=$(trap -p ERR)"
[[ -n $common_handler ]] || common_handler="trap ERR"
common.GetOptions "$@"
shift "$((OPTIND + 1))"
[[ -z $common_command ]] || common_command+="=$"
common_command+='("$common_function" "$@")'
set -E
set +e
trap "common.ErrHandler" ERR
try
eval "$common_command"
yrt
catch; do
"$common_unhandled" >&2
hctac
[[ $common_flags == *E* ]] || set +E
[[ $common_flags != *e* ]] || set -e
[[ $common_flags != *f* || $- == *f* ]] || set -f
[[ $common_flags == *f* || $- != *f* ]] || set +f
eval "$common_handler"
}
নীচে একটি উদাহরণ দেওয়া আছে, যা ধরে নিয়েছে যে উপরের স্ক্রিপ্টটি নামের ফাইলটিতে সংরক্ষিত আছে simple
। makefifo
ফাইল লিপিতে বর্ণনা রয়েছে এই উত্তর । অনুমান করা হয় যে নামের ফাইলটি 4444kkkkk
বিদ্যমান নেই, সুতরাং একটি ব্যতিক্রম ঘটতে পারে। ls 4444kkkkk
কমান্ড থেকে ত্রুটি বার্তা আউটপুট যথাযথ catch
ব্লকের অভ্যন্তরে স্বয়ংক্রিয়ভাবে চাপা দেওয়া হবে ।
#!/bin/bash
#
if [[ $0 != ${BASH_SOURCE[0]} ]]; then
bash "${BASH_SOURCE[0]}" "$@"
return
fi
source simple
source makefifo
MyFunction3() {
echo "entered MyFunction3" >&4
echo "This is from MyFunction3"
ls 4444kkkkk
echo "leaving MyFunction3" >&4
}
MyFunction2() {
echo "entered MyFunction2" >&4
value="$(MyFunction3)"
echo "leaving MyFunction2" >&4
}
MyFunction1() {
echo "entered MyFunction1" >&4
local "flag=false"
try
(
echo "start of try" >&4
MyFunction2
echo "end of try" >&4
)
yrt
catch "[1-3]" "*" "Exception\ Type:\ ERR"; do
echo 'start of catch "[1-3]" "*" "Exception\ Type:\ ERR"'
local -i "i"
echo "-------------------------------------------------"
echo "Status: $(GetStatus)"
echo "Messages:"
for ((i=0; i<$(MessageCount); i++)); do
echo "$(GetMessage "$i")"
done
echo "-------------------------------------------------"
break
echo 'end of catch "[1-3]" "*" "Exception\ Type:\ ERR"'
hctac >&4
catch "1 3 5" "*" -n "Exception\ Type:\ ERR"; do
echo 'start of catch "1 3 5" "*" -n "Exception\ Type:\ ERR"'
echo "-------------------------------------------------"
echo "Status: $(GetStatus)"
[[ $(MessageCount) -le 1 ]] || echo "$(GetMessage "1")"
echo "-------------------------------------------------"
break
echo 'end of catch "1 3 5" "*" -n "Exception\ Type:\ ERR"'
hctac >&4
catch; do
echo 'start of catch' >&4
echo "failure"
flag="true"
echo 'end of catch' >&4
hctac
finally
echo "in finally"
yllanif >&4
"$flag" || echo "success"
echo "leaving MyFunction1" >&4
} 2>&6
ErrHandler() {
echo "EOF"
DefaultErrHandler "$@"
echo "Function: $3"
while read; do
[[ $REPLY != *EOF ]] || break
echo "$REPLY"
done
}
set -u
echo "starting" >&2
MakeFIFO "6"
TryCatchFinally -e -h ErrHandler -o /dev/fd/4 -v result /dev/fd/6 MyFunction1 4>&2
echo "result=$result"
exec >&6-
উপরের স্ক্রিপ্টটি ব্যবহার করে পরীক্ষা করা হয়েছিল GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin17)
। এই স্ক্রিপ্টটি চালানো থেকে আউটপুট নীচে প্রদর্শিত হবে।
starting
entered MyFunction1
start of try
entered MyFunction2
entered MyFunction3
start of catch "[1-3]" "*" "Exception\ Type:\ ERR"
-------------------------------------------------
Status: 1
Messages:
Orginal Status: 1
Exception Type: ERR
Function: MyFunction3
ls: 4444kkkkk: No such file or directory
-------------------------------------------------
start of catch
end of catch
in finally
leaving MyFunction1
result=failure
নীচে প্রদর্শিত স্ক্রিপ্টের সাথে throw
ফাংশন প্রতিস্থাপন করে একটি ব্যবহার করে এমন আরেকটি উদাহরণ তৈরি করা যেতে পারে MyFunction3
।
MyFunction3() {
echo "entered MyFunction3" >&4
echo "This is from MyFunction3"
throw "3" "Orginal Status: 3" "Exception Type: throw"
echo "leaving MyFunction3" >&4
}
throw
কমান্ডের জন্য সিনট্যাক্সটি নীচে দেওয়া হয়েছে। যদি কোনও পরামিতি উপস্থিত না থাকে, তবে স্থিতি এবং পরিবর্তিত স্থানে থাকা বার্তাগুলি পরিবর্তে ব্যবহৃত হবে।
throw [status] [message ...]
পরিবর্তিত স্ক্রিপ্ট সম্পাদন করা থেকে আউটপুট নীচে প্রদর্শিত হবে।
starting
entered MyFunction1
start of try
entered MyFunction2
entered MyFunction3
start of catch "1 3 5" "*" -n "Exception\ Type:\ ERR"
-------------------------------------------------
Status: 3
Exception Type: throw
-------------------------------------------------
start of catch
end of catch
in finally
leaving MyFunction1
result=failure