শেবাংয়ের একাধিক যুক্তি


32

আমি ভাবছি শিবাং লাইন ( #!) এর মাধ্যমে এক্সিকিউটেবলের কাছে একাধিক বিকল্পগুলি পাস করার সাধারণ উপায় আছে কি না ।

আমি নিক্সস ব্যবহার করি এবং আমি যে কোনও স্ক্রিপ্টে শেবাংয়ের প্রথম অংশটি সাধারণত লিখি /usr/bin/env। তার পরে আমার যে সমস্যার মুখোমুখি হচ্ছে তা হ'ল তার পরে যা কিছু আসে তার সিস্টেম দ্বারা একটি ফাইল বা ডিরেক্টরি হিসাবে ব্যাখ্যা করা হয়।

ধরুন, উদাহরণস্বরূপ, আমি bashপোস্টিক্স মোড দ্বারা চালিত করার জন্য একটি স্ক্রিপ্ট লিখতে চাই । শেবাং লেখার সহজ উপায় হ'ল:

#!/usr/bin/env bash --posix

তবে ফলাফলের স্ক্রিপ্টটি কার্যকর করার চেষ্টা করে নিম্নলিখিত ত্রুটিটি তৈরি হয়:

/usr/bin/env: ‘bash --posix’: No such file or directory

আমি এই পোস্টটি সম্পর্কে সচেতন , কিন্তু আমি আরও সাধারণ এবং ক্লিনার সমাধান আছে কিনা তা ভাবছিলাম।


সম্পাদনা : আমি জানি যে গিলি স্ক্রিপ্টগুলির জন্য, আমি যা চাই তা অর্জন করার একটি উপায় আছে যা ম্যানুয়ালটির ৪.৩.৪ বিভাগে নথিযুক্ত :

 #!/usr/bin/env sh
 exec guile -l fact -e '(@ (fac) main)' -s "$0" "$@"
 !#

কৌশলটি, এখানে, দ্বিতীয় লাইনটি (শুরু দিয়ে exec) কোড হিসাবে ব্যাখ্যা করা shহয়েছে, তবে #!... !#ব্লকের মধ্যে থাকা , একটি মন্তব্য হিসাবে, এবং এভাবে গিলি ইন্টারপ্রেটার দ্বারা উপেক্ষা করা হয়েছে।

এই পদ্ধতিটি কোনও দোভাষীর কাছে সাধারণ করা সম্ভব হবে না?


দ্বিতীয় সম্পাদনা : অল্প অল্প করে খেলার পরে, মনে হয় যে দোভাষী যারা তাদের ইনপুটটি পড়তে পারেন তাদের stdinজন্য নিম্নলিখিত পদ্ধতিটি কাজ করবে:

#!/usr/bin/env sh
sed '1,2d' "$0" | bash --verbose --posix /dev/stdin; exit;

এটি সম্ভবত সর্বোত্তম নয়, যদিও shদোভাষী তার কাজ শেষ না করা পর্যন্ত প্রক্রিয়াটি বেঁচে থাকে। কোন প্রতিক্রিয়া বা পরামর্শ প্রশংসা করা হবে।


1
সম্পর্কিত: unix.stackexchange.com
963

উত্তর:


27

কোনও সাধারণ সমাধান নেই, কমপক্ষে আপনার যদি লিনাক্স সমর্থন করার প্রয়োজন হয় তবে তা নয়, কারণ লিনাক্স কার্নেল শেবাং লাইনের প্রথম "শব্দ" অনুসরণ করে সমস্ত কিছুকে একক যুক্তি হিসাবে বিবেচনা করে

আমি নিক্সসসের সীমাবদ্ধতাগুলি কী তা নিশ্চিত নই তবে সাধারণত আমি কেবল আপনার শেবাং লিখি

#!/bin/bash --posix

বা, যেখানে সম্ভব, স্ক্রিপ্টে বিকল্পগুলি সেট করুন :

set -o posix

বিকল্পভাবে, আপনি যথাযথ শেল ডাকে অনুরোধের মাধ্যমে স্ক্রিপ্টটি পুনরায় আরম্ভ করতে পারেন:

#!/bin/sh -

if [ "$1" != "--really" ]; then exec bash --posix -- "$0" --really "$@"; fi

shift

# Processing continues

এই পদ্ধতিকে অন্য ভাষাগুলিতে সাধারণীকরণ করা যেতে পারে, যতক্ষণ না আপনি লক্ষের ভাষা দ্বারা প্রথম দু'টি লাইনের (যা শেল দ্বারা ব্যাখ্যা করা হয়) উপেক্ষা করার উপায় খুঁজে পান।

গনুহ coreutils' envসংস্করণ 8.30 থেকে কার্যসংক্রান্ত প্রদান করে, দেখতে unode এর উত্তর জানার জন্য। (এটি ডেবিয়ান 10 এবং তার পরে, আরএইচএল 8 এবং তার পরে, উবুন্টু 19.04 এবং তার পরে ইত্যাদি উপলভ্য রয়েছে)


18

যদিও ঠিক পোর্টেবল নয়, কোর্টিলগুলি 8.30 দিয়ে শুরু করা হয়েছে এবং এর ডকুমেন্টেশন অনুসারে আপনি ব্যবহার করতে সক্ষম হবেন:

#!/usr/bin/env -S command arg1 arg2 ...

সুতরাং দেওয়া:

$ cat test.sh
#!/usr/bin/env -S showargs here 'is another' long arg -e "this and that " too

তুমি পাবে:

% ./test.sh 
$0 is '/usr/local/bin/showargs'
$1 is 'here'
$2 is 'is another'
$3 is 'long'
$4 is 'arg'
$5 is '-e'
$6 is 'this and that '
$7 is 'too'
$8 is './test.sh'

এবং আপনি যদি কৌতূহলী হন showargsতা হ'ল:

#!/usr/bin/env sh
echo "\$0 is '$0'"

i=1
for arg in "$@"; do
    echo "\$$i is '$arg'"
    i=$((i+1))
done

ভবিষ্যতের রেফারেন্সের জন্য এটি জানতে খুব ভাল।
জন ম্যাকগিহি

বিকল্প FreeBSD 'র থেকে কপি করা হয়েছে envযেখানে -S2005. দেখুন যোগ করা হয়েছিল lists.gnu.org/r/coreutils/2018-04/msg00011.html
Stéphane Chazelas

ফেডোরার 29
এরিক

@ ইউনোড এর কিছু উন্নতি করেছেন showargs: পেস্টবিন. com/q9m6xr8H এবং পেস্টবিন. com/gS8AQ5WA (ওয়ান-লাইনার)
এরিক

অবগতির জন্য: coreutils 8.31 থেকে, envতার নিজস্ব অন্তর্ভুক্ত showargs: -v বিকল্প যেমন#!/usr/bin/env -vS --option1 --option2 ...
chocolateboy

9

POSIX মানটি বিবরণে খুব সংক্ষিপ্ত #!:

সিস্টেম ইন্টারফেসের পরিবারের ডকুমেন্টেশনের যৌক্তিক বিভাগexec() থেকে :

কিছু historicalতিহাসিক বাস্তবায়ন শেল স্ক্রিপ্টগুলি হ্যান্ডেল করে এমন একটি উপায় হ'ল ফাইলের প্রথম দুটি বাইট অক্ষরীয় স্ট্রিং হিসাবে স্বীকৃতি দিয়ে এবং ফাইলটির #!প্রথম লাইনের অবশিষ্ট অংশটি ব্যবহার করতে কমান্ড ইন্টারপ্রেটারের নাম হিসাবে ব্যবহার করা।

থেকে শেল ভূমিকা অধ্যায় :

শেল একটি ফাইল (দেখুন তার ইনপুট সার্চ shথেকে,) -cবিকল্প বা থেকে system()এবং popen()ফাংশন POSIX.1-2008 সিস্টেম ইন্টারফেস ভলিউম সংজ্ঞায়িত। শেল কমান্ডের কোনও ফাইলের প্রথম লাইনটি যদি অক্ষর দিয়ে শুরু হয় #!, ফলাফলগুলি অনির্ধারিত

মূলত এর অর্থ হ'ল যে কোনও বাস্তবায়ন (আপনি যে ইউনিক্সটি ব্যবহার করছেন) শেবাং লাইনের পার্সিংয়ের স্পেসিফিকেশনগুলি যেমন চান তা করতে বিনামূল্যে।

কিছু ইউনিস, যেমন ম্যাকোস (এটিএম পরীক্ষা করতে পারে না), শেবাং লাইনে দোভাষীকে প্রদত্ত যুক্তিগুলিকে পৃথক যুক্তিতে বিভক্ত করবে, অন্যদিকে লিনাক্স এবং অন্যান্য ইউনিসিস দোভাষীকে একক বিকল্প হিসাবে যুক্তি দেবে।

এইভাবে শেবাং লাইন একক যুক্তির চেয়ে বেশি গ্রহণ করতে সক্ষম হওয়ার উপর নির্ভর করা বোকামি।

আরও দেখুন উইকিপিডিয়াতে কুঁড়েঘর প্রবন্ধের পোর্টেবিলিটি অধ্যায়


একটি সহজ সমাধান, যা যে কোনও ইউটিলিটি বা ভাষার ক্ষেত্রে জেনারালাইজড, একটি মোড়ক স্ক্রিপ্ট তৈরি করা যা যথাযথ কমান্ড লাইনের যুক্তি দিয়ে আসল স্ক্রিপ্টটি কার্যকর করে:

#!/bin/sh
exec /bin/bash --posix /some/path/realscript "$@"

আমি মনে করি না আমি ব্যক্তিগতভাবে এটি পুনরায় চালানো চেষ্টা করবে না নিজেই যে হিসাবে কিছুটা ভঙ্গুর মতানুযায়ী।


7

শেবাংকে execve(২) ম্যান পৃষ্ঠায় নিম্নরূপ বর্ণনা করা হয়েছে :

#! interpreter [optional-arg]

এই বাক্য গঠনে দুটি স্পেস গ্রহণ করা হয়েছে:

  1. দোভাষীর পাথের আগে একটি স্থান , তবে এই স্থানটি alচ্ছিক।
  2. দোভাষী এবং তার pathচ্ছিক যুক্তিকে পৃথক করে এমন একটি স্থান ।

নোট করুন যে anচ্ছিক যুক্তির কথা বলার সময় আমি বহুবচনটি ব্যবহার করি নি, উপরের সিনট্যাক্সটিও ব্যবহার করে না [optional-arg ...], কারণ আপনি সর্বাধিক একটি একক যুক্তি সরবরাহ করতে পারেন

যতক্ষণ শেল স্ক্রিপ্টিং সম্পর্কিত, আপনি setআপনার স্ক্রিপ্টের শুরুতে বিল্ট-ইন কমান্ডটি ব্যবহার করতে পারেন যা দোভাষী পরামিতিগুলি সেট করতে দেয়, একই ফলাফল প্রদান করে যেমন আপনি কমান্ড-লাইন আর্গুমেন্ট ব্যবহার করেছেন।

তোমার ক্ষেত্রে:

set -o posix

বাশ প্রম্পট থেকে, help setসমস্ত উপলব্ধ বিকল্প পেতে আউটপুট চেক করুন।


1
আপনার কাছে দুটিরও বেশি জায়গা থাকার অনুমতি রয়েছে, এগুলি কেবলমাত্র argumentচ্ছিক যুক্তির অংশ হিসাবে বিবেচিত হচ্ছে।
স্টিফেন কিট

@ স্টেফেনকিট: প্রকৃতপক্ষে, এখানে সাদা স্থানকে প্রকৃত স্থানের চরের চেয়ে আরও বেশি বিভাগ হিসাবে নেওয়া উচিত। আমি মনে করি যে অন্যান্য সাদা স্থান যেমন ট্যাবগুলিও ব্যাপকভাবে গ্রহণ করা উচিত।
হোয়াইটওয়ানটারওয়াল্ফ

3

লিনাক্সে, শিবাং খুব নমনীয় নয়; একাধিক উত্তর অনুসারে ( স্টিফেন কিটের উত্তর এবং জার্গ ডব্লু মিতাগের ), শেবাং লাইনে একাধিক যুক্তি পাস করার কোনও নির্ধারিত উপায় নেই।

এটি কারও কাজে আসবে কিনা তা সম্পর্কে আমি নিশ্চিত নই, তবে অভাবের বৈশিষ্ট্যটি বাস্তবায়নের জন্য আমি একটি শর্ট স্ক্রিপ্ট লিখেছি। Https://gist.github.com/loxaxs/7cbe84aed1c38cf18f70d8427bed1efa দেখুন ।

এম্বেড থাকা ওয়ার্কআরউন্ডগুলি লেখাও সম্ভব। হ্যালো, আমি একই পরীক্ষার স্ক্রিপ্টে প্রয়োগ চারটি ভাষা-অজ্ঞাস্তিক কাজের ক্ষেত্র এবং ফলাফল প্রতিটি মুদ্রণ উপস্থাপন করি। আমি অনুমান যে স্ক্রিপ্ট এক্সিকিউটেবল এবং হয় /tmp/shebang


প্রক্রিয়া প্রতিস্থাপনের ভিতরে আপনার স্ক্রিপ্টটিকে ব্যাশ বংশগতভাবে মোড়ানো

আমি যতদূর জানি, এটি করার পক্ষে এটি নির্ভরযোগ্য ভাষা-অজ্ঞাতদৃষ্টির উপায়। এটি আর্গুমেন্টগুলি পাস করার অনুমতি দেয় এবং স্টিডিন সংরক্ষণ করে। ত্রুটিটি হ'ল দোভাষী তার পড়া ফাইলটির (আসল) অবস্থান জানেন না।

#!/bin/bash
exec python3 -O <(cat << 'EOWRAPPER'
print("PYTHON_SCRIPT_BEGINNING")

from sys import argv
try:
    print("input() 0 ::", input())
    print("input() 1 ::", input())
except EOFError:
    print("input() caused EOFError")
print("argv[0]   ::", argv[0])
print("argv[1:]  ::", argv[1:])
print("__debug__ ::", __debug__)
# The -O option changes __debug__ to False

print("PYTHON_SCRIPT_END")
EOWRAPPER
) "$@"

কলিং echo -e 'aa\nbb' | /tmp/shebang 'arg1' 'arg2 contains spaces' 'arg3\ uses\ \\escapes\\'প্রিন্টস:

PYTHON_SCRIPT_BEGINNING
input() 0 :: aa
input() 1 :: bb
argv[0]   :: /dev/fd/62
argv[1:]  :: ['arg1', 'arg2 contains spaces', 'arg3\\ uses\\ \\\\escapes\\\\']
__debug__ :: False
PYTHON_SCRIPT_END

নোট করুন যে প্রক্রিয়া প্রতিস্থাপন একটি বিশেষ ফাইল উত্পাদন করে। এটি সমস্ত এক্সিকিউটেবলের পক্ষে উপযুক্ত নয়। উদাহরণস্বরূপ, #!/usr/bin/lessঅভিযোগ:/dev/fd/63 is not a regular file (use -f to see it)

জানি না ড্যাশ প্রক্রিয়া প্রতিস্থাপনের ভিতরে হেরেডোক রাখা সম্ভব কিনা।


আপনার স্ক্রিপ্টটিকে সাধারণ বংশানুক্রমে মোড়ানো

সংক্ষিপ্ত এবং সহজ, তবে আপনি stdinআপনার স্ক্রিপ্ট থেকে অ্যাক্সেস করতে পারবেন না এবং এর জন্য কোনও স্ক্রিপ্টটি পড়তে এবং চালিত করতে দোভাষীর প্রয়োজন হয় stdin

#!/bin/sh
exec python3 - "$@" << 'EOWRAPPER'
print("PYTHON_SCRIPT_BEGINNING")

from sys import argv

try:
    print("input() 0 ::", input())
    print("input() 1 ::", input())
except EOFError:
    print("input() caused EOFError")
print("argv[0]   ::", argv[0])
print("argv[1:]  ::", argv[1:])
print("__debug__ ::", __debug__)
# The -O option changes __debug__ to False

print("PYTHON_SCRIPT_END")
EOWRAPPER

কলিং echo -e 'aa\nbb' | /tmp/shebang 'arg1' 'arg2 contains spaces' 'arg3\ uses\ \\escapes\\'প্রিন্টস:

PYTHON_SCRIPT_BEGINNING
input() caused EOFError
argv[0]   :: -
argv[1:]  :: ['arg1', 'arg2 contains spaces', 'arg3\\ uses\\ \\\\escapes\\\\']
__debug__ :: True
PYTHON_SCRIPT_END

অ্যাডক system()কল ব্যবহার করুন তবে তর্ক ছাড়াই

সম্পাদিত ফাইলটির নামটি সঠিকভাবে পাস করে তবে আপনার স্ক্রিপ্টটি আপনি যে আর্গুমেন্টগুলি দিয়েছেন তা গ্রহণ করবে না। দ্রষ্টব্য যে আমি জানি কেবলমাত্র সেই ভাষাটি যার পরিচিতিদাতা উভয়ই ডিফল্টরূপে লিনাক্সটিতে ইনস্টল থাকে এবং কমান্ড লাইন থেকে তার নির্দেশাবলী ডিফল্টরূপে পড়ে।

#!/usr/bin/gawk BEGIN {system("python3 -O " ARGV[1])}
print("PYTHON_SCRIPT_BEGINNING")

from sys import argv

print("input() 0 ::", input())
print("input() 1 ::", input())
print("argv[0]   ::", argv[0])
print("argv[1:]  ::", argv[1:])
print("__debug__ ::", __debug__)
# The -O option changes __debug__ to False

print("PYTHON_SCRIPT_END")

কলিং echo -e 'aa\nbb' | /tmp/shebang 'arg1' 'arg2 contains spaces' 'arg3\ uses\ \\escapes\\'প্রিন্টস:

PYTHON_SCRIPT_BEGINNING
input() 0 :: aa
input() 1 :: bb
argv[0]   :: /tmp/shebang
argv[1:]  :: []
__debug__ :: False
PYTHON_SCRIPT_END

system()আপনার আর্গুমেন্টে ফাঁকা স্থান না থাকলে শুরুর দিকে 4.1+ কল ব্যবহার করুন

দুর্দান্ত, তবে কেবলমাত্র যদি আপনি নিশ্চিত হন যে আপনার স্ক্রিপ্টটি ফাঁকা স্থান যুক্তি দিয়ে কল করা হবে না। যেমন আপনি দেখতে পাচ্ছেন, ফাঁকা স্থানগুলি এড়ানো না হলে আপনার যুক্তিগুলি স্পেসে বিভক্ত হবে।

#!/usr/bin/gawk @include "join"; BEGIN {system("python3 -O " join(ARGV, 1, ARGC, " "))}
print("PYTHON_SCRIPT_BEGINNING")

from sys import argv

print("input() 0 ::", input())
print("input() 1 ::", input())
print("argv[0]   ::", argv[0])
print("argv[1:]  ::", argv[1:])
print("__debug__ ::", __debug__)
# The -O option changes __debug__ to False

print("PYTHON_SCRIPT_END")

কলিং echo -e 'aa\nbb' | /tmp/shebang 'arg1' 'arg2 contains spaces' 'arg3\ uses\ \\escapes\\'প্রিন্টস:

PYTHON_SCRIPT_BEGINNING
input() 0 :: aa
input() 1 :: bb
argv[0]   :: /tmp/shebang
argv[1:]  :: ['arg1', 'arg2', 'contains', 'spaces', 'arg3 uses \\escapes\\']
__debug__ :: False
PYTHON_SCRIPT_END

4.1 নিচে awk সংস্করণ জন্য, আপনি, লুপ জন্য একটি ভিতরে স্ট্রিং সংযুক্তকরণের ব্যবহার উদাহরণস্বরূপ ফাংশন দেখতে হব আর https://www.gnu.org/software/gawk/manual/html_node/Join-Function.html


1
বাধা $variableবা `command`প্রতিস্থাপনের জন্য এখানে ডকুমেন্ট টার্মিনেটরটি উদ্ধৃত করুন :exec python3 -O <(cat <<'EOWRAPPER'
জন ম্যাকগিহি

2

(শেবাং) লাইনে LD_LIBRARY_PATHঅজগর দিয়ে ব্যবহার করার কৌশল #!যা খোল ছাড়া অন্য কোনও কিছুর উপর নির্ভর করে না এবং ট্রিট কাজ করে:

#!/bin/sh
'''' 2>/dev/null; exec /usr/bin/env LD_LIBRARY_PATH=. python -x "$0" "$@" #'''

__doc__ = 'A great module docstring'

এই পৃষ্ঠায় অন্যত্র যেমনটি ব্যাখ্যা করা হয়েছে তেমন কিছু শেল shতাদের স্ট্যান্ডার্ড ইনপুটটিতে একটি স্ক্রিপ্ট নিতে পারে।

আমরা যে স্ক্রিপ্টটি দিয়েছি shতাতে কমান্ডটি কার্যকর করার চেষ্টা করা হয়েছে ''''যা ''(খালি স্ট্রিং) দ্বারা সরল করা হয়েছে shএবং অবশ্যই কোনও ''আদেশ নেই বলে এটি কার্যকর করতে ব্যর্থ হয় , সুতরাং এটি সাধারণত line 2: command not foundস্ট্যান্ডার্ড ত্রুটি বর্ণনাকারীর আউটপুট হয় তবে আমরা এই বার্তাটি ব্যবহার করে পুনঃনির্দেশ 2>/dev/nullকরি নিকটতম ব্ল্যাকহোল কারণ এটি ব্যবহারকারীর কাছে shএটি প্রদর্শন করতে দিতে অগোছালো এবং বিভ্রান্তিকর লাগবে।

তারপরে আমরা আমাদের আগ্রহের আদেশে এগিয়ে execযাই : যা বর্তমান শেল প্রক্রিয়াটি আমাদের ক্ষেত্রে অনুসরণ করে প্রতিস্থাপন করে: /usr/bin/env pythonপর্যাপ্ত পরামিতি সহ:

  • "$0" অজগরটিকে এটি স্ক্রিপ্টটি খোলা এবং ব্যাখ্যা করা উচিত এবং এটিও সেট করা উচিত sys.argv[0]
  • "$@"sys.argv[1:]স্ক্রিপ্ট কমান্ড লাইনে প্রদত্ত তর্কগুলিতে অজগরটিকে সেট করতে।

এবং আমরা পরিবেশ পরিবর্তনশীল envসেট করতে বলি LD_LIBRARY_PATH, এটি হ্যাকের একমাত্র পয়েন্ট।

শেল কমান্ডটি মন্তব্য দিয়ে শুরু হয় #যাতে শেলটি ট্রেলিং ট্রিপল উদ্ধৃতি উপেক্ষা করে '''

shতারপরে পাইথন ইন্টারপ্রেটারের একটি চটকদার নতুন দৃষ্টান্ত দ্বারা প্রতিস্থাপন করা হয় যা প্রথম আর্গুমেন্ট (দ্য "$0") হিসাবে প্রদত্ত পাইথন উত্স স্ক্রিপ্টটি খোলে এবং পড়ে read

পাইথন ফাইলটি খুলে -xযুক্তিটির জন্য উত্সটির প্রথম লাইনটি এড়িয়ে যায় । দ্রষ্টব্য: এটি ছাড়াও কাজ করে -xকারণ পাইথনের পক্ষে একটি শেবাং কেবল একটি মন্তব্য

পাইথন এর পরে ২ য় লাইনটিকে বর্তমান মডিউল ফাইলের জন্য ডক্ট্রিং হিসাবে ব্যাখ্যা করে, সুতরাং আপনার যদি কোনও বৈধ মডিউল ডক্ট্রিং প্রয়োজন __doc__হয় তবে উপরের উদাহরণের মতো আপনার পাইথন প্রোগ্রামে প্রথম জিনিসটি সেট করুন ।



একটি খালি স্ট্রিংটি দেওয়া হচ্ছে… উম… খালি, আপনি আপনার কমান্ডটি বানরের ব্যবসায়ের সন্ধান না পেয়ে ফেলে দিতে সক্ষম হবেন: ''''exec ...কাজটি করা উচিত। এক্সিকিউটিভের পূর্বে কোনও স্থান নোট করুন বা এটি খালি কমান্ডটি সন্ধান করবে। আপনি খালিটি প্রথম আর্গের উপর ছড়িয়ে দিতে চান তাই $0ঠিক exec
কালেব

1

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

#!/usr/bin/awk BEGIN{system("bash --posix "ARGV[1])}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.