শেল প্রম্পটে আপনি যেমন লিখবেন তেমন উদ্ধৃত শেল স্ক্রিপ্ট কি তার যুক্তি মুদ্রণ করতে পারে?


9

শেল স্ক্রিপ্টে, আমার বোধগম্যতা হ'ল "$@"স্ক্রিপ্ট আর্গুমেন্টগুলিতে প্রসারিত হয়, প্রয়োজনীয় হিসাবে তাদের উদ্ধৃত করে। উদাহরণস্বরূপ, এটি স্ক্রিপ্ট আর্গুমেন্টগুলিকে জিসিসি তে ফরোয়ার্ড করে:

gcc -fPIC "$@"

<<<যদিও ব্যাশ পাস-টু-স্টিডিন সিনট্যাক্স ব্যবহার করার সময় , "@$"আমি যেমনটি আশা করব তেমন কাজ করে না।

#!/bin/bash
cat <<< "$@"

স্ক্রিপ্ট কে কল করা হচ্ছে যেমন ./test.sh foo "bar baz"দেয়

foo bar baz

আমি আশা করব

foo "bar baz"

শেল স্ক্রিপ্ট লেখার জন্য কি এমন কোনও উপায় আছে যা শেল প্রম্পটে লেখার সাথে সাথে এর আর্গুমেন্টগুলি মুদ্রণ করে? উদাহরণস্বরূপ: ইঙ্গিতটিতে স্ক্রিপ্ট আর্গুমেন্ট সহ পরবর্তী কমান্ডটি কী ব্যবহার করা উচিত সে সম্পর্কে একটি ইঙ্গিত।

উত্তর:


5

ঠিক আছে, "$@"অবস্থানগত পরামিতিগুলির তালিকায় প্রসারিত হয়, অবস্থানগত পরামিতিগুলির জন্য একটি যুক্তি।

যখন তুমি কর:

set '' 'foo bar' $'blah\nblah'
cmd "$@"

cmdএই 3 টি আর্গুমেন্টের সাথে আহ্বান করা হচ্ছে: খালি স্ট্রিং foo barএবং blah<newline>blah। শেলটি execve()সিস্টেম কলকে এমন কিছু দিয়ে কল করবে :

execve("/path/to/cmd", ["cmd", "", "foo bar", "blah\nblah"], [envvars...]);

আপনি যদি শেল কমান্ড লাইনটি পুনরায় গঠন করতে চান (এটি শেল ভাষার কোড) যা একই অনুরোধটি পুনরুত্পাদন করতে পারে, আপনি যেমন কিছু করতে পারেন:

awk -v q="'" '
  function shellquote(s) {
    gsub(q, q "\\" q q, s)
    return q s q
  }
  BEGIN {
    for (i = 1; i < ARGC; i++) {
      printf "%s", sep shellquote(ARGV[i])
      sep = " "
    }
    printf "\n"
  }' cmd "$@"

বা সহ zsh, বিভিন্ন ধরণের উদ্ধৃতি চাওয়া:

set '' 'foo bar' $'blah\nblah'
$ print -r -- cmd "${(q)@}"
cmd '' foo\ bar blah$'\n'blah
$ print -r -- cmd "${(qq)@}"
cmd '' 'foo bar' 'blah
blah'
$ print -r -- cmd "${(qqq)@}"
cmd "" "foo bar" "blah
blah"
$ print -r -- cmd "${(qqqq)@}"
cmd $'' $'foo bar' $'blah\nblah'

বা সহ zsh, bashবা ksh93( bashঅন্যান্য শাঁসের সাথে এখানে ওয়াইএমএমভি):

$ set '' 'foo bar' $'blah\nblah'
$ printf cmd; printf ' %q' "$@"; printf '\n'
cmd '' foo\ bar $'blah\nblah'

আপনি শেলটির xtrace বিকল্পটিও ব্যবহার করতে পারেন যা শেলটি এটি কার্যকর করতে চলেছে তা মুদ্রণের কারণ করে:

(PS4=; set -x; : cmd "$@")
: cmd '' 'foo bar' 'blah
blah'

উপরে, আমরা যুক্তিরূপে :কোনও অপ-কমান্ড cmdএবং অবস্থানগত পরামিতিগুলি চালিয়েছি। আমার শেল এগুলি শেলের পুনর্নির্মাণের জন্য উপযুক্ত একটি দুর্দান্ত উদ্ধৃত ফ্যাশনে মুদ্রিত করেছে। সমস্ত শেল এটি করে না।


5
`"$@"` expands to the script arguments, quoting them as needed

না, এটি হয় না। প্রোগ্রামকে কল করা আর্গুমেন্টগুলির একটি তালিকা নেয় , প্রতিটি যুক্তি একটি স্ট্রিং। যখন আপনি শেল প্রোগ্রাম চালানো ./test.sh foo "bar baz", এই তিনটি আর্গুমেন্ট সহ একটি কল তৈরী করে: ./test.sh, foo, এবং bar baz। (জিরোথ আর্গুমেন্টটি প্রোগ্রামের নাম; এটি প্রোগ্রামগুলিকে কী নামে ডাকা হয় তা এটি জানতে দেয়)) কোট করা শেলটির একটি বৈশিষ্ট্য, প্রোগ্রাম কলগুলির বৈশিষ্ট্য নয়। শেলটি কল করার সময় এই তালিকাটি তৈরি করে।

"$@"স্ক্রিপ্টে পাস হওয়া আর্গুমেন্টের তালিকাটি সরাসরি অনুলিপি করে বা কলটি ব্যবহৃত হয় সেখানে কল্পনা যুক্তিগুলির তালিকায় ফাংশন করে। এই তালিকায় কোনও শেল পার্সিং করা হয়নি বলে কোনও উদ্ধৃতি জড়িত নেই।

ইন cat <<< "$@", আপনি এমন "$@"প্রসঙ্গে ব্যবহার করছেন যেখানে একক স্ট্রিংয়ের প্রয়োজন। <<<Operator` একটি স্ট্রিং, না স্ট্রিং একটি তালিকা প্রয়োজন। এই প্রসঙ্গে, বাশ তালিকার উপাদানগুলিকে নিয়ে যায় এবং তাদের মধ্যে একটি জায়গার সাথে যোগ দেয়।

স্ক্রিপ্ট ডিবাগিংয়ের জন্য, যদি আপনি চালনা করেন set -x( set +xবন্ধ করতে), এটি একটি ট্রেস মোড সক্রিয় করে যেখানে প্রতিটি কমান্ড কার্যকর হওয়ার আগে মুদ্রিত হয়। ব্যাশে, সেই ট্রেসটির উদ্ধৃতি রয়েছে যা কমান্ডটি শেলের মধ্যে পেস্ট করা সম্ভব করে (এটি প্রতিটি shবাস্তবায়নের ক্ষেত্রে সত্য নয় )।

যদি আপনার কাছে একটি স্ট্রিং থাকে এবং আপনি এটিকে শেল উত্স সিনট্যাক্সে রূপান্তর করতে চান যা মূল স্ট্রিংটিতে ফিরে আসে তবে আপনি এটি একক উদ্ধৃতি দিয়ে ঘিরে রাখতে পারেন এবং স্ট্রিংয়ের অভ্যন্তরে প্রতিটি একক উদ্ধৃতি দিয়ে প্রতিস্থাপন করতে পারেন '\''

for x do
  printf %s "'${x//\'/\'\\\'\'}' "
done
echo

স্ট্রিং প্রতিস্থাপন বাক্য গঠনটি ksh93 / bash / zsh / mksh- নির্দিষ্ট- সরল sh এ, আপনাকে স্ট্রিংটির উপরে লুপ করতে হবে।

for raw do
  quoted=
  while case "$raw" in *\'*) true;; *) false;; esac; do
    quoted="$quoted'\\''${raw%%\'*}"
    raw="${raw#*\'}"
  done
  printf %s "'$quoted$raw' "
done
echo

2

"$@" স্ক্রিপ্ট আর্গুমেন্ট প্রসারিত, প্রয়োজন হিসাবে তাদের উদ্ধৃত

ভাল ধরণের. ব্যবহারিক উদ্দেশ্যে যা যথেষ্ট কাছাকাছি হওয়া উচিত এবং রেফারেন্স ম্যানুয়ালটিতে এটি বলে"$@" is equivalent to "$1" "$2" ...

সুতরাং, দুটি পরামিতি সহ fooএবং bar baz, এগুলি এক রকম হবে:

echo "$@"
echo "$1" "$2"
echo "foo" "bar baz"

(ব্যতীত যদি প্যারামিটারগুলিতে কেবল সরল স্ট্রিংয়ের পরিবর্তে বিশেষ অক্ষর থাকে তবে সেগুলি প্রসারিত করার পরে আবার প্রসারিত হবে না $@এবং $1...)

তবে আমরা $@যদি উদ্ধৃতিগুলিতে প্যারামিটারগুলি দ্বারা প্রতিস্থাপন বিবেচনা করি তবে উদ্ধৃতিগুলি echoদেখার জন্য থাকবে না , একইভাবে এর সাথে কোটগুলিও gccপাওয়া যায় না।

<<<"$@"== "$1" "$2" ...নিয়মের ব্যতিক্রম কিছুটা , এটি স্পষ্টভাবে উল্লেখ করেছে যে The result is supplied as a single string to the command on its standard inputপ্যারামিটার এবং ভেরিয়েবল সম্প্রসারণ এবং অন্যদের মধ্যে উদ্ধৃতি অপসারণের পরে। সুতরাং যথারীতি, <<< "foo"কেবল fooইনপুট হিসাবে দেয় , একইভাবে somecmd "foo"কেবল fooএকটি আর্গুমেন্ট হিসাবে দেয় ।

স্ক্রিপ্টটিকে কল করা ./test.sh foo "bar baz"[...] আমি আশা করব foo "bar baz"

উক্তিটি যদি থেকে যায় তবে তা এখনও হতে হবে "foo" "bar baz"। শেল বা কোনও চলমান কমান্ডের কোন ধারণা নেই যে কমান্ডটি সঞ্চালিত হওয়ার পরে উদ্ধৃতিটি কী ছিল। বা যদি কথা বলার জন্য কোনও উদ্ধৃতিও পাওয়া যায়, সিস্টেম কলটি কেবল নাল-টার্মিনেটেড স্ট্রিংগুলির একটি তালিকা পেয়ে থাকে এবং উদ্ধৃতিগুলি কেবল শেল ভাষার বৈশিষ্ট্য। অন্যান্য ভাষায় অন্যান্য সম্মেলন থাকতে পারে।


0

বাশের জন্য বিকল্প বিকল্প

q='"'; t=( "${@/#/$q}" ); u=( "${t[@]/%/$q}" ); echo ${u[@]}

বাশ নেস্টেড বিকল্পগুলি সমর্থন করে না, সুতরাং কীভাবে অ্যারেটিকে পুনরায় সাইন ইন করতে হবে তা দেখানোর জন্য /programming/12303974/assign-array-to-variable#12304017 কে ধন্যবাদ । অ্যারে, সম্প্রসারণ এবং প্যাটার্নের বিকল্পের (প্যারামিটার বিস্তারের অধীনে) বিশদ জানতে man bash( https://linux.die.net/man/1/bash ) দেখুন ।

বিশ্লেষণ

বাশ কমান্ড লাইন প্যারামিটারগুলিকে একটি অ্যারে হিসাবে রাখে $@

q উদ্ধৃতি চরিত্র ধারণ করে।

প্যারামিটার বিস্তারের চারপাশে ডাবল উদ্ধৃতি ${ ... }পৃথক প্যারামিটারগুলিকে পৃথক উপাদান হিসাবে সংরক্ষণ করে এবং এগুলিতে মোড়ানো ( )আপনাকে এগুলি একটি ভেরিয়েবলের অ্যারে হিসাবে নির্ধারণ করতে দেয়।

/#/$qএকটি প্যারামিটার সম্প্রসারণে প্যাটার্নের শুরুতে (রেগেক্সের মতো ^) উদ্ধৃতি লেখার বিকল্প রয়েছে।

/%/$qএকটি প্যারামিটার সম্প্রসারণে প্যাটার্নের শেষটি (রেজেেক্সের মতো $) উদ্ধৃতি চার্টের সাথে প্রতিস্থাপিত করে ।

কেস ব্যবহার করুন: কমান্ড লাইন থেকে ইমেল ঠিকানার তালিকার জন্য মাইএসকিউএল অনুসন্ধান করা

ভিন্ন উদ্ধৃতি চর ব্যবহার করতে, পরামিতিগুলির মধ্যে কমা যোগ করতে এবং চূড়ান্ত কমাটি সরিয়ে ফেলার জন্য উপরের বিবৃতিতে কয়েকটি পরিবর্তন রয়েছে। এবং অবশ্যই মাইএসকিএল আহ্বানে পাসওয়ার্ডটি রেখে আমি খারাপ হয়ে যাচ্ছি। সুতরাং আমাকে মামলা করুন

q="'"; t=( "${@/#/$q}" ); u="${t[@]/%/$q,}"; v="u.email in( ${u%,} )"
mysql -uprod_program -h10.90.2.11 -pxxxxxxxxxxxx my_database <<END
select ...
from users u
join ....
where $v # <<<<<<<<<<<<<<<<<< here is where all the hard work pays off :-)
group by user_id, prog_id
;
END

কেবলমাত্র নোট করুন যে ডাবল-কোট দিয়ে উদ্ধৃতি ব্যাকস্ল্যাশ, $-স্প্যাশন এবং অন্যান্য ডাবল-কোট রক্ষা করতে খুব কার্যকর নয় । এই কারণেই অন্যান্য উত্তরগুলি স্ট্রিংয়ের ভিতরে একক উদ্ধৃতিগুলি পরিচালনা করতে কিছু দৈর্ঘ্যে যাওয়ার সময় একক উদ্ধৃতি ব্যবহার করে বা স্ট্রিংয়ের একটি উদ্ধৃত অনুলিপি তৈরির জন্য শেলের নিজস্ব বৈশিষ্ট্য ব্যবহার করে।
ইলক্কাচু

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