বিপরীত ক্রমে শেল আর্গুমেন্ট মুদ্রণ করুন


12

আমি কিছুটা আটকে আছি। আমার কাজটি হ'ল তৃতীয় এবং চতুর্থ ব্যতীত আমার স্ক্রিপ্টে যুক্তিগুলি বিপরীত ক্রমে মুদ্রণ করা।

আমার কাছে যা আছে তা এই কোড:

#!/bin/bash

i=$#
for arg in "$@"
do
    case $i
    in
        3) ;;
        4) ;;
        *) eval echo "$i. Parameter: \$$i";;
    esac
    i=`expr $i - 1`
done

যেমন আমি ঘৃণা করি (পিএইচপি-র শুভেচ্ছা), আমি এটি ছাড়া সমাধানের সন্ধান করছি তবে আমি এর সন্ধান করতে পারছি না।

আমি যুক্তির অবস্থান কীভাবে গতিশীলভাবে সংজ্ঞায়িত করতে পারি?

পিএস: এটি কোনও হোম ওয়ার্ক নয়, আমি পরীক্ষার শেল শিখছি তাই আমি পুরানো পরীক্ষার সমাধানের চেষ্টা করি।

উত্তর:


13

evalগতিশীলভাবে-বেছে নেওয়া অবস্থানের দ্বারা পজিশনাল প্যারামিটারটি অ্যাক্সেস করার একমাত্র পোর্টেবল উপায়। মানগুলি (যা আপনি ব্যবহার করছেন না) এর পরিবর্তে সূচকে স্পষ্টভাবে লুপ করলে আপনার স্ক্রিপ্টটি আরও পরিষ্কার হবে। মনে রাখবেন যে exprআপনার স্ক্রিপ্টটি পুরানো বোর্ন শেলগুলিতে চালানো না চাইলে আপনার প্রয়োজন হবে না ; $((…))পাটিগণিতটি পসিক্সে রয়েছে। evalক্ষুদ্রতম সম্ভাব্য খণ্ডের ব্যবহার সীমাবদ্ধ করুন ; উদাহরণস্বরূপ, ব্যবহার করবেন না eval echo, একটি অস্থায়ী ভেরিয়েবলের মান নির্ধারণ করুন।

i=$#
while [ "$i" -gt 0 ]; do
  if [ "$i" -ne 3 ] && [ "$i" -ne 2 ]; then
    eval "value=\${$i}"
    echo "Parameter $i is $value"
  fi
  i=$((i-1))
done

ব্যাশে আপনি ${!i}যার প্যারামিটারটির নাম সেটি বোঝাতে ব্যবহার করতে পারেন $i। এটি যখন $iনামযুক্ত প্যারামিটার বা একটি সংখ্যা হয় (অবস্থানিক পরামিতি নির্দেশ করে) কাজ করে। আপনি এটির সময়ে, আপনি অন্যান্য ব্যাশ সুবিধার বৈশিষ্ট্যগুলি ব্যবহার করতে পারেন।

for ((i=$#; i>0; i--)); do
  if ((i != 3 && i != 4)); then
    echo "Parameter $i is ${!i}"
  fi
done

argতারা সঠিকভাবে অর্ডার করা হয়েছে এবং বিপরীতে নয় বলে আমি ব্যবহার করতে পারি না । এর ব্যবহারের ক্ষেত্রে expr, আমি কেবলমাত্র মান ব্যবহার করতেই সীমাবদ্ধ।
ওয়ারেনফেইথ

1
@ ওয়ারেনফেইথ যদি আপনার স্ক্রিপ্টটি শুরু হয় #!/bin/bash, আপনি ${!i}এবং ব্যবহার করতে পারেন (())। আপনি যদি স্ট্যান্ডার্ড শের সাথে লেগে থাকতে চান তবে এগুলি উপলভ্য নয় তবে $((…))তা।
গিলস 16'10

ঠিক আছে, আমি মনে করি আমি এটি নিয়ে কাজ করতে পারি :)
ওয়ারেনফেইথ

নোট করুন যে এন্টিক বোর্ন শেলগুলি যাইহোক, 9 ডলার ছাড়িয়ে অবস্থানীয় পরামিতিগুলিতে অ্যাক্সেস করতে সক্ষম হবে না।
স্টাফেন চেজেলাস

1
evalহয় না শুধুমাত্র পোর্টেবল পথ রায়ান দেখিয়েছেন হিসাবে
স্টাফেন চেজেলাস

7

আমি reverseআমার পথে একটি স্ক্রিপ্ট রেখেছি যা এটি করে:

#!/bin/sh

if [ "$#" -gt 0 ]; then
    arg=$1
    shift
    reverse "$@"
    printf '%s\n' "$arg"
fi

ব্যবহারের উদাহরণ:

$ reverse a b c '*' '-n'
-n
*
c
b
a

আপনি ডেডিকেটেড স্ক্রিপ্টের পরিবর্তে কোনও ফাংশনও ব্যবহার করতে পারেন।


মনে রাখবেন যে একটি (এখনও অবধি পোস্ট করা অন্যান্য জবাবগুলির বিপরীতে) বর্ন শেলটিতেও কাজ করবে (আজকাল সেই শেলটি ব্যবহার করার কোনও কারণ নেই)
স্টাফেন চাজেলাস

@ স্টাফেনচাজেলাস: উদ্ধৃতি কেন $#? এটি একটি অ-নেতিবাচক পূর্ণসংখ্যা ছাড়া অন্য কিছু হতে পারে?
জি-ম্যান

2
@ জি-ম্যান, তালিকার প্রসঙ্গে একটি পরিবর্তনশীলকে অবিচ্ছিন্ন রেখে স্প্লিট + গ্লোব অপারেটরকে ডেকে আনছেন। আপনি এখানে এটি চাওয়ার কারণ নেই। ভেরিয়েবলের বিষয়বস্তুর সাথে এর কোনও যোগসূত্র নেই। শেষের দিকে unix.stackexchange.com/a/171347 দেখুন । আরও মনে রাখবেন যে কয়েকটি শেল (উদাহরণস্বরূপ ড্যাশ, প্যাশ) এখনও পরিবেশ থেকে আইএফএসের উত্তরাধিকারী।
স্টাফেন চেজেলাস

আমি এটি পেয়েছি, অ্যান্ড্রয়েডে, আমাকে ঘোষণা করতে হয়েছিলlocal arg=$1
স্টারফ্রাই

2

এটি eval এর সঠিক এবং অ-বিপজ্জনক ব্যবহার। আপনি যে সামগ্রীটি প্রবেশ করছেন তা আপনি সম্পূর্ণরূপে নিয়ন্ত্রণ করুন eval

যদি এটি এখনও আপনাকে খারাপ অনুভূতি দেয়, তবে আপনি যদি পোর্টেবিলিটিটির বিষয়ে চিন্তা না করেন তবে আপনি বাশের ${!i}ইন্ডিরিশন সিনট্যাক্স ব্যবহার করতে পারেন ।


তাহলে ${!i}কি স্ট্যান্ডার্ড সিনট্যাক্সের অংশ নয়?
ওয়ারেনফেইথ

না এটি বাশীবাদ। এখানে পসিএক্স
শন জে গফ

2

ধরে নিচ্ছি অবস্থানগত পরামিতিগুলিতে নতুন লাইন অক্ষর নেই:

[ "$#" -gt 0 ] && printf '%s\n' "$@" | #print in order
sed '3,4 d' |                          #skip 3 and 4
tac                                    #reverse (try tail -r on
                                       #non-GNU systems).

টেস্ট:

set 1 2 3 4 5 6
printf '%s\n' "$@" | 
sed '3,4 d' |
tac

পরীক্ষার আউটপুট:

6
5
2
1

1

সহ zsh:

$ set a 'foo bar' c '' '*'
$ printf '<%s>\n' "${(Oa)@}"
<*>
<>
<c>
<foo bar>
<a>

Oaবিপরীত অ্যারে সূচকগুলিতে বিস্তারের উপরে অ্যারে উপাদানগুলিকে সাজানোর জন্য একটি প্যারামিটার এক্সপেনশন পতাকা ।

3 এবং 4 বাদ দিতে:

$ printf '<%s>\n' "${(Oa)@[5,-1]}" "${(Oa)@[1,2]}"
<*>
<foo bar>
<a>

0

মূলত যে কোনও শেল সহ:

printf '{ PS4=\${$(($#-$x))}; } 2>&3; 2>&1\n%.0s' |
x=LINENO+1 sh -sx "$@" 3>/dev/null

এবং আপনার সাব-শেলগুলি ব্যবহার করার দরকার নেই । উদাহরণ স্বরূপ:

set -x a b c
{ last= PS4=\${last:=\${$#}}; set +x; } 2>/dev/null
echo "$last"

... কপি করে প্রিন্ট ...

c

এবং এখানে একটি শেল ফাংশন যা আপনার জন্য একটি শেল সেট করতে পারে যা aliasআর্গুমেন্টগুলি সামনে বা পিছনে মুদ্রণ করবে:

tofro() case $1 in (*[!0-9]*|'') ! :;;(*) set "$1"
        until   [ "$1" -eq "$(($#-1))" ]    &&
                shift && alias args=":; printf \
            \"%.\$((\$??\${#*}:0))s%.\$((!\$??\${#*}:0))s\n\" $* "
        do      [ "$#" -gt 1 ] &&
                set "$@ \"\${$#}\" " '"${'"$((1+$1-$#))"'}"' ||
                set "$1" '"$1" "${'"$1"'}"'
        done;   esac

এটি কোনও আর্গুমেন্টের জন্য আক্ষরিক মান সংরক্ষণ করার চেষ্টা করে না, বরং এটি এর মধ্যে একটি স্ট্রিং রাখে args alias:

:;printf    "%.$(($??${#*}:0))s%.$((!$??${#*}:0))s\n" \
            "$1" "${3}" "${2}"  "${2}" "${3}"  "${1}"

... এবং তাই কেবল পরামিতিগুলির পিছনে এবং সামনের দিকে রেফারেন্স সঞ্চয় করে। এটি একটি আর্গুমেন্ট হিসাবে দেওয়া হিসাবে এটি একটি গণনা পর্যন্ত সঞ্চয় করবে। এবং তাই উপরের aliasমত উত্পন্ন হয়েছিল:

tofro 3

printfপূর্ববর্তী কমান্ডের রিটার্ন মানের উপর ভিত্তি করে এর আচরণ প্রভাবিত হয় - যা সর্বদা :নাল আদেশ, এবং তাই সাধারণত সত্য। printfপ্রতিটি বার এটি প্রিন্ট করলে তার অর্ধেকটি আর্গুমেন্ট এড়িয়ে যাবে - যা ডিফল্টরূপে আর্গুমেন্টকে ক্ষুদ্রতম থেকে বৃহত্তর সংখ্যাতে মুদ্রণ করে আনে। তবে, আপনি যদি কেবল এটি করেন:

! args

... এটি তাদের বিপরীতে মুদ্রণ করে।

যেহেতু উপনামটি কোনও আক্ষরিক মান সংরক্ষণ করে না, প্রকৃত অর্গগুলি পরিবর্তিত হতে পারে তার মান স্থির থাকে তবে এটি এখনও যতটা প্রাসঙ্গিক হতে পারে তা উল্লেখ করবে। উদাহরণ স্বরূপ:

set one two three
tofro 3
args; ! args
shift; args; ! args

... যা ছাপায় ...

one
two
three
three
two
one
two
three


three
two

তবে উপন্যাসটি পুনরায় সেট করার কাজটি করা যেতে পারে:

tofro 2
args; ! args

... এবং তাই এটি প্রিন্ট ...

two
three
three
two

-3
declare -a argv=( "$@" )
for (( i=$((${#argv[@]}-1)) ; i>=0 ; i=$(($i-1)) )) ; do
        echo "${argv[$i]}"
        # use "${argv[$i]}" in here...
done

2
মোটেও কোন ব্যাখ্যা নেই, দুর্দান্ত। আমার কাছ থেকে ডাউনওয়েট করুন আপনার কোডটি কী করে তা ব্যাখ্যা করুন এবং আমি আমার ধারণা পরিবর্তন করতে পারি।
ওয়ারেনফেইথ

3
সরল করা যেতে পারেfor ((i = $# - 1; i >= 0; i--))
স্টাফেন চ্যাজেলাস

আমি কি হ্যালুসিনেট করছি? আমি ভেবেছিলাম যে প্রশ্নটিতে আমি শব্দগুলি দেখেছি যা বলেছিল "তৃতীয় এবং চতুর্থটি বাদ দিয়ে ... যুক্তিগুলি মুদ্রণ করুন"।
জি-ম্যান

1
@ জি-ম্যান, শিরোনামটি "বিপরীতে মুদ্রিত যুক্তিগুলি মুদ্রণ করে" বলে যা এটি উত্তর ব্যবহার না করে উত্তর দিচ্ছে। এর থেকে 3 এবং 4 বাদ দিলে তুচ্ছ। আমি ভাবি না যে ডাউনভোটগুলি ন্যায়সঙ্গত? এটি স্ব-ব্যাখ্যামূলকও (যদিও আমি বলেছি যে একটি বিরাট ব্যাপার সহজ করা যেতে পারে)।
স্টাফেন চেজেলাস
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.