একটি এখন মোছা এর লেখা উত্তর দ্বারা VonC ।
রবার্ট গাম্বলের সুসংযোগ উত্তরটি সরাসরি প্রশ্নের সাথে ডিল করে। এটি শূন্যস্থান সহ ফাইলের নাম সহ কিছু ইস্যুতে প্রশস্ত করে।
আরও দেখুন: bin {1: + "$ @"} ইন / বিন / শ মধ্যে
বেসিক থিসিস: "$@"
সঠিক, এবং $*
(উদ্ধৃত) প্রায় সর্বদা ভুল is এটি কারণ "$@"
সূক্ষ্মভাবে কাজ করে যখন যুক্তিগুলিতে ফাঁক থাকে এবং $*
যখন না হয় তখন একইভাবে কাজ করে । কিছু পরিস্থিতিতে, "$*"
ঠিক আছে তবে "$@"
সাধারণত (তবে সর্বদা নয়) একই জায়গায় কাজ করে। উদ্ধৃত, $@
এবং $*
সমতুল্য (এবং প্রায় সর্বদা ভুল)।
সুতরাং, এর মধ্যে পার্থক্য কি $*
, $@
, "$*"
, এবং "$@"
? এগুলি সমস্ত 'শেলের সমস্ত যুক্তি' সম্পর্কিত, তবে তারা বিভিন্ন জিনিস করে। যখন উদ্ধৃতিহীন, $*
এবং $@
একই জিনিস করুন। তারা প্রতিটি 'শব্দ' (অ-সাদা অংশের ক্রম) পৃথক যুক্তি হিসাবে বিবেচনা করে। উদ্ধৃত ফর্মগুলি একেবারে আলাদা, যদিও: "$*"
যুক্তি তালিকার একটি একক স্থান-বিভাজিত স্ট্রিং "$@"
হিসাবে বিবেচনা করে , যেখানে আর্গুমেন্টগুলি ঠিক ঠিক একইভাবে আচরণ করে যেমন কমান্ড লাইনে নির্দিষ্ট করার সময়।
"$@"
কোনও অবস্থানগত যুক্তি না থাকলে কিছুতেই প্রসারিত হয়; "$*"
একটি খালি স্ট্রিংয়ে প্রসারিত - এবং হ্যাঁ, এটির পার্থক্য রয়েছে, যদিও এটি উপলব্ধি করা শক্ত। (অ-মানক) কমান্ড প্রবর্তনের পরে নীচে আরও তথ্য দেখুন al
।
সেকেন্ডারি থিসিস: আপনার যদি ফাঁকা জায়গা দিয়ে তর্কগুলি প্রক্রিয়াকরণের দরকার হয় এবং তারপরে এগুলি অন্য কমান্ডগুলিতে প্রেরণ করা প্রয়োজন, তবে আপনাকে সহায়তার জন্য কখনও কখনও আপনার অ-মানক সরঞ্জামের প্রয়োজন হয়। (অথবা আপনার সাবধানতার সাথে অ্যারে ব্যবহার করা উচিত: এর সাথে "${array[@]}"
অ্যালোগুলি আচরণ করে "$@"
))
উদাহরণ:
$ mkdir "my dir" anotherdir
$ ls
anotherdir my dir
$ cp /dev/null "my dir/my file"
$ cp /dev/null "anotherdir/myfile"
$ ls -Fltr
total 0
drwxr-xr-x 3 jleffler staff 102 Nov 1 14:55 my dir/
drwxr-xr-x 3 jleffler staff 102 Nov 1 14:55 anotherdir/
$ ls -Fltr *
my dir:
total 0
-rw-r--r-- 1 jleffler staff 0 Nov 1 14:55 my file
anotherdir:
total 0
-rw-r--r-- 1 jleffler staff 0 Nov 1 14:55 myfile
$ ls -Fltr "./my dir" "./anotherdir"
./my dir:
total 0
-rw-r--r-- 1 jleffler staff 0 Nov 1 14:55 my file
./anotherdir:
total 0
-rw-r--r-- 1 jleffler staff 0 Nov 1 14:55 myfile
$ var='"./my dir" "./anotherdir"' && echo $var
"./my dir" "./anotherdir"
$ ls -Fltr $var
ls: "./anotherdir": No such file or directory
ls: "./my: No such file or directory
ls: dir": No such file or directory
$
কেন যে কাজ করে না? এটি কার্যকর হয় না কারণ শেল প্রক্রিয়াগুলি ভেরিয়েবলগুলি প্রসারিত করার আগে উদ্ধৃতি দেয়। সুতরাং, শ্বেতটি এম্বেড করা উদ্ধৃতিগুলিতে মনোযোগ দেওয়ার জন্য $var
আপনাকে ব্যবহার করতে হবে eval
:
$ eval ls -Fltr $var
./my dir:
total 0
-rw-r--r-- 1 jleffler staff 0 Nov 1 14:55 my file
./anotherdir:
total 0
-rw-r--r-- 1 jleffler staff 0 Nov 1 14:55 myfile
$
আপনার কাছে ফাইলের নাম যেমন " He said,
"Don't do this!"
" (কোট এবং ডাবল কোট এবং স্পেস সহ) থাকে তখন এটি সত্যই জটিল হয়ে ওঠে।
$ cp /dev/null "He said, \"Don't do this!\""
$ ls
He said, "Don't do this!" anotherdir my dir
$ ls -l
total 0
-rw-r--r-- 1 jleffler staff 0 Nov 1 15:54 He said, "Don't do this!"
drwxr-xr-x 3 jleffler staff 102 Nov 1 14:55 anotherdir
drwxr-xr-x 3 jleffler staff 102 Nov 1 14:55 my dir
$
শেলগুলি (এগুলির সবগুলি) এ জাতীয় স্টাফগুলি পরিচালনা করা বিশেষত সহজ করে না, তাই (ইউজার্সে যথেষ্ট) অনেকগুলি ইউনিক্স প্রোগ্রামগুলি পরিচালনা করার পক্ষে ভাল কাজ করে না। ইউনিক্সে, একটি ফাইলের নাম (একক উপাদান) স্ল্যাশ এবং NUL ব্যতীত যে কোনও অক্ষর ধারণ করতে পারে '\0'
। যাইহোক, শেলগুলি কোনও শূন্যস্থান বা নিউলাইন বা ট্যাবগুলিকে কোনও পথের নামে কোথাও উত্সাহ দেয়। স্ট্যান্ডার্ড ইউনিক্স ফাইলের নামগুলিতে স্পেস ইত্যাদি থাকে না কেন এটি is
ফাঁকা জায়গা এবং অন্যান্য ঝামেলাযুক্ত অক্ষরগুলি ধারণ করতে পারে এমন ফাইলের নামগুলির সাথে কথা বলার সময়, আপনাকে অত্যন্ত সতর্কতা অবলম্বন করতে হবে এবং আমি অনেক আগেই পেয়েছি যে আমার এমন একটি প্রোগ্রামের দরকার ছিল যা ইউনিক্সের উপর স্ট্যান্ডার্ড নয়। আমি এটি বলি escape
(সংস্করণ 1.1 1989-08-23T16: 01: 45Z তারিখের ছিল)।
এখানে ব্যবহারের একটি উদাহরণ রয়েছে escape
- এসসিসি নিয়ন্ত্রণ ব্যবস্থা সহ। এটি একটি কভার স্ক্রিপ্ট যা একটি delta
(চিন্তাভাবনা চেক-ইন ) এবং একটি
get
(চিন্তাভাবনা চেক-আউট ) করে does বিভিন্ন যুক্তি, বিশেষত -y
(কারণ আপনি কেন পরিবর্তন করেছেন) ফাঁকা এবং নিউলাইনগুলি ধারণ করে। নোট করুন যে স্ক্রিপ্টটি 1992 সালের, তাই এটি $(cmd ...)
স্বরলিপিটির পরিবর্তে ব্যাক-টিক
ব্যবহার #!/bin/sh
করে এবং প্রথম লাইনে ব্যবহার করে না use
: "@(#)$Id: delget.sh,v 1.8 1992/12/29 10:46:21 jl Exp $"
#
# Delta and get files
# Uses escape to allow for all weird combinations of quotes in arguments
case `basename $0 .sh` in
deledit) eflag="-e";;
esac
sflag="-s"
for arg in "$@"
do
case "$arg" in
-r*) gargs="$gargs `escape \"$arg\"`"
dargs="$dargs `escape \"$arg\"`"
;;
-e) gargs="$gargs `escape \"$arg\"`"
sflag=""
eflag=""
;;
-*) dargs="$dargs `escape \"$arg\"`"
;;
*) gargs="$gargs `escape \"$arg\"`"
dargs="$dargs `escape \"$arg\"`"
;;
esac
done
eval delta "$dargs" && eval get $eflag $sflag "$gargs"
(এই দিনগুলিতে আমি সম্ভবত পালানোর বিষয়টি পুরোপুরিভাবে ব্যবহার করব না - -e
যুক্তি দিয়ে এটির দরকার হয় না - তবে সামগ্রিকভাবে এটি আমার সহজ স্ক্রিপ্টগুলি ব্যবহার করে escape
))
escape
প্রোগ্রাম কেবল বরং ভালো, তার আর্গুমেন্ট আউটপুট echo
, কিন্তু এটি নিশ্চিত করে যে আর্গুমেন্ট সাথে ব্যবহারের জন্য সুরক্ষিত হয়
eval
(এর এক স্তর eval
; আমি একটি প্রোগ্রাম যা দূরবর্তী শেল সঞ্চালনের করেনি আছে, এবং যে আউটপুট অব্যাহতি প্রয়োজন escape
)।
$ escape $var
'"./my' 'dir"' '"./anotherdir"'
$ escape "$var"
'"./my dir" "./anotherdir"'
$ escape x y z
x y z
$
আমার আরেকটি প্রোগ্রাম বলা হয়েছে al
যা প্রতি লাইন প্রতি তার আর্গুমেন্টগুলি তালিকাভুক্ত করে (এবং এটি আরও প্রাচীন: সংস্করণ 1.1 তারিখ 1987-01-27T14: 35: 49)। স্ক্রিপ্টগুলি ডিবাগ করার সময় এটি সর্বাধিক উপকারী, কারণ কমান্ডে আসলে কী আর্গুমেন্টগুলি দেওয়া হয় তা দেখার জন্য এটি একটি কমান্ড লাইনে প্লাগ করা যায়।
$ echo "$var"
"./my dir" "./anotherdir"
$ al $var
"./my
dir"
"./anotherdir"
$ al "$var"
"./my dir" "./anotherdir"
$
[ যুক্ত:
এবং এখন বিভিন্ন "$@"
স্বরলিপিগুলির মধ্যে পার্থক্য দেখানোর জন্য , এখানে আরও একটি উদাহরণ দেওয়া হল:
$ cat xx.sh
set -x
al $@
al $*
al "$*"
al "$@"
$ sh xx.sh * */*
+ al He said, '"Don'\''t' do 'this!"' anotherdir my dir xx.sh anotherdir/myfile my dir/my file
He
said,
"Don't
do
this!"
anotherdir
my
dir
xx.sh
anotherdir/myfile
my
dir/my
file
+ al He said, '"Don'\''t' do 'this!"' anotherdir my dir xx.sh anotherdir/myfile my dir/my file
He
said,
"Don't
do
this!"
anotherdir
my
dir
xx.sh
anotherdir/myfile
my
dir/my
file
+ al 'He said, "Don'\''t do this!" anotherdir my dir xx.sh anotherdir/myfile my dir/my file'
He said, "Don't do this!" anotherdir my dir xx.sh anotherdir/myfile my dir/my file
+ al 'He said, "Don'\''t do this!"' anotherdir 'my dir' xx.sh anotherdir/myfile 'my dir/my file'
He said, "Don't do this!"
anotherdir
my dir
xx.sh
anotherdir/myfile
my dir/my file
$
লক্ষ্য করুন যে কিছুই কমান্ড লাইনের ওপরে *
এবং আসল ফাঁকাগুলি সংরক্ষণ করে না */*
। এছাড়াও, নোট করে আপনি শেলটিতে 'কমান্ড লাইন আর্গুমেন্ট' পরিবর্তন করতে পারেন:
set -- -new -opt and "arg with space"
এটি ' -new
', ' -opt
', ' and
' এবং ' arg with space
' 4 টি বিকল্প সেট করে ।
]
হুম, এটি বেশ দীর্ঘ উত্তর - সম্ভবত এক্সাইজেসিসই এটি আরও ভাল শব্দ। escape
অনুরোধের জন্য উপলব্ধ সোর্স কোড (জিমেইল ডট কম এ প্রথম নাম ডট লাস্টনেমে ইমেল) to এর উত্স কোডটি al
অবিশ্বাস্যভাবে সহজ:
#include <stdio.h>
int main(int argc, char **argv)
{
while (*++argv != 0)
puts(*argv);
return(0);
}
এখানেই শেষ. এটি test.sh
রবার্ট গাম্বলি যে স্ক্রিপ্টটি দেখিয়েছিল তার সমান এবং এটি শেল ফাংশন হিসাবে লেখা যেতে পারে (তবে শর্নের কার্যকারিতা বোর্ন শেলের স্থানীয় সংস্করণে উপস্থিত ছিল না যখন আমি প্রথম লিখেছিলাম al
)।
এছাড়াও মনে রাখবেন যে আপনি al
একটি সাধারণ শেল স্ক্রিপ্ট হিসাবে লিখতে পারেন :
[ $# != 0 ] && printf "%s\n" "$@"
শর্তসাপেক্ষে প্রয়োজনীয় যাতে কোনও আর্গুমেন্ট পাস না করে এটি কোনও আউটপুট তৈরি করে না। printf
কমান্ডটি কেবল বিন্যাসের স্ট্রিং আর্গুমেন্ট সহ একটি ফাঁকা রেখা তৈরি করবে, তবে সি প্রোগ্রামটি কিছুই তৈরি করে না।