শেল স্ক্রিপ্টগুলিতে শিফট ব্যবহারের উদ্দেশ্য কী?


117

আমি এই স্ক্রিপ্ট জুড়ে এসেছি:

#! /bin/bash                                                                                                                                                                                           

if (( $# < 3 )); then
  echo "$0 old_string new_string file [file...]"
  exit 0
else
  ostr="$1"; shift
  nstr="$1"; shift  
fi

echo "Replacing \"$ostr\" with \"$nstr\""
for file in $@; do
  if [ -f $file ]; then
    echo "Working with: $file"
    eval "sed 's/"$ostr"/"$nstr"/g' $file" > $file.tmp 
    mv $file.tmp $file
  fi  
done

তারা যেখানে রেখা ব্যবহার করে তার অর্থ কী shift? আমার ধারণা, স্ক্রিপ্টটি কমপক্ষে যুক্তি দিয়ে ব্যবহার করা উচিত তাই ...?

উত্তর:


140

shiftএটি একটি bashঅন্তর্নির্মিত যা ধরণের আর্গুমেন্ট তালিকার শুরু থেকে যুক্তি সরিয়ে দেয়। প্রদত্ত যে স্ক্রিপ্ট দেওয়া 3 আর্গুমেন্ট পাওয়া যায় $1, $2, $3, তারপর কলে shift করতে হবে $2নতুন $1। এ shift 2দু'জনকে $1পুরানো করে নতুন করে বদলানো হবে $3। আরো তথ্যের জন্য, এখানে দেখুন:


25
+1 টি নোট এটা না আবর্তিত তাদের, এটা নাড়াচাড়া তাদের (আর্গুমেন্ট) অ্যারে। শিফট / আনশিফ্ট এবং পপ / পুশ এই সাধারণ ধরণের হেরফেরের সাধারণ নাম (দেখুন, উদাহরণস্বরূপ, ব্যাশের pushdএবং popd)।
স্বর্ণলোক


@ গুডিলোকস খুব সত্য। "ঘোরান" এর পরিবর্তে আমার আরও একটি শব্দ ব্যবহার করার উপায়টি আরও ভালভাবে খুঁজে পাওয়া উচিত ছিল, "আর্গুমেন্ট ভেরিয়েবলগুলিতে যুক্তিগুলিকে এগিয়ে নিয়ে যাওয়া" এর মতো কিছু। যাইহোক আমি আশা করি পাঠ্যের উদাহরণগুলি এবং রেফারেন্সের লিঙ্কটি তবে তা পরিষ্কার করে দিয়েছে।
humanityANDpeace

যদিও স্ক্রিপ্টটিতে উল্লেখ করা হয়েছে bash, প্রশ্নটি সমস্ত শেলের কাছে সাধারণ, সুতরাং পিক্সিক্স স্ট্যান্ডার্ডটি বিরাজ করে: pubs.opengroup.org/onlinepubs/9699919799/utilities/…
ক্যালান্দোয়া

32

স্বর্ণকেশ 'মন্তব্য এবং মানবতা রেফারেন্স বর্ণনা হিসাবে, shiftঅবস্থানগত মাপদণ্ডগুলি (reassigns $1, $2ইত্যাদি), যাতে $1পুরোনো মান লাগে $2, $2এর মান লাগে $3ইত্যাদি *   পুরোনো মান $1বাতিল করা হয়। ( $0পরিবর্তিত হয় না)) এটি করার কয়েকটি কারণের মধ্যে রয়েছে:

  • এটি আপনাকে দশম যুক্তি (যদি একটি থাকে তবে) আরও সহজে অ্যাক্সেস করতে দেয়।  $10কাজ করে না - এটিকে সংক্ষিপ্ত হিসাবে ব্যাখ্যা করা $1হয় 0 (এবং এরকম কিছু তৈরি হতে পারে Hello0)। একটি পরে shift, দশম যুক্তি হয়ে যায় $9। (তবে, বেশিরভাগ আধুনিক শেলগুলিতে আপনি ব্যবহার করতে পারেন ${10}))
  • বাশ গাইডের জন্য যেমন প্রারম্ভিকরা দেখায়, এটি আর্গুমেন্টের মাধ্যমে লুপ করতে ব্যবহৃত হতে পারে। আইএমএনএসএইচও, এটি আনাড়ি; forতার জন্য অনেক ভাল।
  • আপনার উদাহরণের স্ক্রিপ্টের মতো, কিছু যুক্তি বাদে সমস্ত আর্গুমেন্টকে একইভাবে প্রক্রিয়া করা সহজ করে তোলে। উদাহরণস্বরূপ, আপনার স্ক্রিপ্টে $1এবং $2পাঠ্যের স্ট্রিংগুলি রয়েছে $3এবং অন্যান্য সমস্ত পরামিতিগুলি ফাইলের নাম।

সুতরাং এটি এখানে কীভাবে খেলবে তা এখানে। মনে করুন আপনার স্ক্রিপ্টটি বলা হয় Patryk_scriptএবং এটি হিসাবে ডাকা হয়

Patryk_script USSR Russia Treaty1 Atlas2 Pravda3

স্ক্রিপ্ট দেখে

$1 = USSR
$2 = Russia
$3 = Treaty1
$4 = Atlas2
$5 = Pravda3

স্টেটমেন্টটি ostr="$1"ভেরিয়েবল সেট ostrকরে USSR। প্রথম shiftবিবৃতিটি নিম্নরূপে অবস্থানগত পরামিতিগুলিকে পরিবর্তন করে:

$1 = Russia
$2 = Treaty1
$3 = Atlas2
$4 = Pravda3

স্টেটমেন্টটি nstr="$1"ভেরিয়েবল সেট nstrকরে Russia। দ্বিতীয় shiftবিবৃতিটি অবস্থানগত পরামিতিগুলিকে নিম্নরূপ পরিবর্তন করে:

$1 = Treaty1
$2 = Atlas2
$3 = Pravda3

এবং তারপর forলুপ পরিবর্তন USSR( $ostr) এর Russia( $nstr) ফাইলের মধ্যে Treaty1, Atlas2এবং Pravda3



স্ক্রিপ্ট নিয়ে কয়েকটি সমস্যা রয়েছে।

  1. ফাইলের জন্য $ @; করা

    যদি স্ক্রিপ্টটি হিসাবে ডাকা হয়

    প্যাট্রিক_স্ক্রিপ্ট ইউএসএসআর রাশিয়া চুক্তি 1 "ওয়ার্ল্ড অ্যাটলাস 2" প্রভদা 3

    এটা দেখে

    $ 1 = ইউএসএসআর
    $ 2 = রাশিয়া
    $ 3 = সন্ধি 1
    $ 4 = ওয়ার্ল্ড অ্যাটলাস 2
    $ 5 = প্রভদা 3

    কিন্তু, কারণ $@উদ্ধৃত করা হয় না, আপনার স্থান World Atlas2উদ্ধৃত নয়, এবং forলুপ মনে চার ফাইল আছে: Treaty1, World, Atlas2, এবং Pravda3। এটি হয় হওয়া উচিত

    "$ @" এ ফাইলের জন্য; করা

    (আর্গুমেন্টে কোনও বিশেষ চরিত্রের উদ্ধৃতি দিতে) বা সহজভাবে

    ফাইল করার জন্য

    (যা দীর্ঘ সংস্করণের সমতুল্য)।

  2. eval "sed 's /" ostr "/" $ nstr "/ g' $ ফাইল"

    এটি হওয়ার দরকার নেই eval, এবং চেক না করা ব্যবহারকারী ইনপুট একটিতে evalবিপদজনক হতে পারে। উদাহরণস্বরূপ, যদি স্ক্রিপ্টটি হিসাবে ডাকা হয়

    প্যাট্রিক_স্ক্রিপ্ট "'; আরএম *;'" রাশিয়া চুক্তি 1 অ্যাটলাস 2 প্রভদা 3

    এটি কার্যকর করা হবে rm *! যদি এটি ব্যবহারকারীর চেয়ে উচ্চতর সুবিধাসহ স্ক্রিপ্টটি চালানো যায় তবে এটি বড় উদ্বেগের বিষয়; উদাহরণস্বরূপ, যদি এটি sudoওয়েব ইন্টারফেসের মাধ্যমে চালানো বা আহ্বান করা যায়। এটি সম্ভবত এত গুরুত্বপূর্ণ নয় যদি আপনি কেবল নিজের ডিরেক্টরিতে এটি নিজের ডিরেক্টরিতে ব্যবহার করেন। তবে এতে পরিবর্তন করা যায়

    সেড "s / $ অস্টার / $ nstr / জি" "$ ফাইল"

    এটি এখনও কিছু ঝুঁকি আছে, কিন্তু তারা খুব কম গুরুতর।

  3. if [ -f $file ], > $file.tmpএবং যথাক্রমে mv $file.tmp $file হওয়া উচিত if [ -f "$file" ], > "$file.tmp"এবং mv "$file.tmp" "$file"ফাইলের নামগুলি হ্যান্ডেল করার জন্য যেগুলিতে স্পেস (বা অন্যান্য মজার অক্ষর) থাকতে পারে। ( eval "sed …কমান্ডটি ফাইলের নামগুলিও ফাঁক করে দেয় যার মধ্যে স্পেস রয়েছে))


* shift একটি alচ্ছিক যুক্তি নেয়: একটি ধনাত্মক পূর্ণসংখ্যা যা কতগুলি পরামিতি স্থানান্তরিত করতে হবে তা নির্দিষ্ট করে। ডিফল্ট হ'ল একটি ( 1)। উদাহরণস্বরূপ, shift 4কারণ $5 পরিণত $1, $6পরিণত $2, ইত্যাদি। (দ্রষ্টব্যদের জন্য বাশ গাইডের উদাহরণটি ভুল হিসাবে লক্ষ্য করুন Note ) এবং তাই আপনার স্ক্রিপ্টটি বলতে পরিবর্তন করা যেতে পারে

ostr="$1"
nstr="$2"
shift 2

যা আরও স্পষ্ট বলে বিবেচিত হতে পারে।



শেষ নোট / সতর্কতা:

উইন্ডোজ কমান্ড প্রম্পট (ব্যাচ ফাইল) ভাষাও একটি SHIFTকমান্ড সমর্থন করে, যা মূলত shiftইউনিক্স শেলের কমান্ডের মতো একই কাজ করে, যার মধ্যে একটি উল্লেখযোগ্য পার্থক্য রয়েছে, যা আমি লোককে বিভ্রান্ত হওয়ার হাত থেকে রক্ষা করার চেষ্টা করার জন্য আড়াল করব:

  • একটি আদেশ SHIFT 4যেমন একটি ত্রুটি, "SHIFT কমান্ডে অবৈধ পরামিতি" ত্রুটি বার্তা দেয়।
  • SHIFT /n, যেখানে n0 থেকে 8 এর মধ্যে পূর্ণসংখ্যা হয়, এটি বৈধ - তবে এটি সময় বদলে যায় না । এটা তোলে একবার শিফ্ট, দিয়ে শুরু এন  ম যুক্তি। তাই কারণ (পঞ্চম যুক্তি) পরিণত পরিণত , ইত্যাদি, একা 3 মাধ্যমে আর্গুমেন্ট 0 রেখে।n SHIFT /4%5%4,  %6%5


2
shiftপ্রয়োগ করা যেতে পারে while, untilএবং এমনকি forএকটি সহজ পারেন চেয়ে অনেক বেশী সূক্ষ্ম উপায়ে অ্যারে পরিচালনা করার জন্য loops forলুপ। আমি প্রায়শই এর forমতো লুপগুলিতে এটি দরকারী মনে করি ... set -f -- $args; IFS=$split; for arg do set -- $arg; shift "${number_of_fields_to_discard}" && fn_that_wants_split_arg "$arg"; done
মাইকসার্ভ

3

এর সহজ ব্যাখ্যা এটি। আদেশটি বিবেচনা করুন:

/bin/command.sh SET location Cebu
/bin/command.sh SET location Cebu, Philippines 6014 

আপনার সহায়তা ছাড়াই shiftলোকেশনটির সম্পূর্ণ মানটি বের করতে পারবেন না কারণ এই মানটি নির্বিচারে দীর্ঘ হতে পারে। আপনি যখন দুইবার স্থানান্তরিত করবেন, তখন আরগগুলি SETএবং locationএমন সরানো হবে:

x="$@"
echo "location = $x"

$@জিনিসটি খুব দীর্ঘ তাকান । এর অর্থ, এটি xস্পেস এবং কমা থাকা সত্ত্বেও এটি সম্পূর্ণরূপে পরিবর্তনশীল হিসাবে সংরক্ষণ করতে পারে । সুতরাং সংক্ষেপে, আমরা কল করি shiftএবং তারপরে আমরা ভেরিয়েবল থেকে কী বাকী থাকে তার মান পুনরুদ্ধার করি $@

আপডেট আমি একটি সংক্ষিপ্ত স্নিপেটের নীচে যুক্ত করছি যা ধারণা shiftছাড়াও এর কার্যকারিতা এবং দক্ষতাগুলি দেখায় , ক্ষেত্রগুলি সঠিকভাবে উত্তোলন করা খুব কঠিন কাজ হবে।

#!/bin/sh
#

[ $# -eq 0 ] && return 0

a=$1
shift
b=$@
echo $a
[ -n "$b" ] && echo $b

ব্যাখ্যা : এর পরে shift, ভেরিয়েবল বিতে ফাঁকা স্থান বা অন্যান্য বিষয় বিবেচনা না করে বাকী বাকী উপাদান থাকবে The [ -n "$b" ] && echo $bএটি একটি সুরক্ষা যা আমরা কেবল খালি প্রিন্ট করি যদি এর কোনও বিষয়বস্তু থাকে।


(1) এটি সহজ ব্যাখ্যা নয়। এটি একটি আকর্ষণীয় কোণ। (২) তবে যতক্ষণ আপনি একগুচ্ছ যুক্তি (বা তাদের সবগুলি) একত্রিত করতে চান, আপনি "$*"পরিবর্তে ব্যবহার করার অভ্যাসে যেতে চাইবেন "$@"। (3) আমি আপনার উত্তরটিকে উর্ধ্বে তুলতে যাচ্ছিলাম, কিন্তু আমি তা করি নি, কারণ আপনি "দুবার শিফট" বলছেন কিন্তু আপনি কোডটিতে আসলে এটি প্রদর্শন করেন না। (৪) আপনি যদি কোনও স্ক্রিপ্ট চান যাতে কমান্ড লাইন থেকে বহু-শব্দের মান নিতে সক্ষম হয় তবে সম্ভবত ব্যবহারকারীকে পুরো মানটি উদ্ধৃতিতে রাখাই ভাল। … (চালিয়ে যাওয়া)
স্কট

(চালিয়ে যাওয়া) ... আপনি আজ যত্নশীল নাও হতে পারেন, তবে আপনার পদ্ধতির সাহায্যে আপনি একাধিক স্পেস ( Philippines   6014), শীর্ষস্থানীয় স্থান, চলার স্থান বা ট্যাব রাখতে পারবেন না। (5) বিটিডাব্লু, আপনি এখানে ব্যাশে যা করছেন তা করতে সক্ষম হতে পারেন x="${*:3}"
স্কট

আমি যেখানে আপনার '*** একাধিক স্পেস অনুমতি দেয় না সেখানে বোঝার চেষ্টা করেছি ***' মন্তব্যটি এসেছে কারণ এটি shiftআদেশের সাথে সম্পর্কিত নয় । আপনি সম্ভবত tle @ বনাম $ * সূক্ষ্ম পার্থক্য উল্লেখ করছেন। তবে বাস্তব এখনও অব্যাহত রয়েছে যে উপরে আমার স্নিপেটটি যথাযথভাবে স্থানটি বের করতে পারে এটির যতগুলি স্পেস রয়েছে তা পিছনে রয়েছে বা সামনের অংশে এটি কোনও ব্যাপার নয়। স্থানান্তরিত হওয়ার পরে, অবস্থানটিতে সঠিক অবস্থান থাকবে।
টাইপেলজিক

2

shift কমান্ড লাইন আর্গুমেন্টগুলিকে একটি FIFO সারি হিসাবে বিবেচনা করুন, প্রতিবার যখন এটি আহ্বান করা হয় তখন এটি পপলফিট উপাদান দেয়।

array = [a, b, c]
shift equivalent to
array.popleft
[b, c]
$1, $2,$3 can be interpreted as index of the array.
$# is the length of array
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.