VonC විසින් දැන් මකා දැමූ පිළිතුරක් නැවත ලියන්න .
රොබට් ගැම්බල්ගේ සාරාංශගත පිළිතුර කෙලින්ම ප්රශ්නය සමඟ කටයුතු කරයි. මෙය අවකාශයන් අඩංගු ගොනු නාමයන් සමඟ ඇති සමහර ගැටලු පුළුල් කරයි.
මෙයද බලන්න: b {1: + "$ @"} in / bin / sh
මූලික නිබන්ධනය: "$@"
නිවැරදි වන අතර $*
(නම් නොකල) සෑම විටම පාහේ වැරදිය. මෙයට හේතුව "$@"
, තර්ක වල අවකාශයන් ඇති විට හොඳින් ක්රියා කරන අතර $*
ඒවා නොමැති විට මෙන් ක්රියා කරයි . සමහර තත්වයන් තුළ, "$*"
හරි, නමුත් "$@"
සාමාන්යයෙන් (නමුත් සෑම විටම නොවේ) එකම ස්ථානවල ක්රියා කරයි. නොකියන ලද $@
අතර $*
සමාන වේ (සෑම විටම පාහේ වැරදිය).
ඒ නිසා, එම වෙනස $*
, $@
, "$*"
, හා "$@"
? ඒවා සියල්ලම 'කවචයට ඇති සියලුම තර්ක' හා සම්බන්ධ නමුත් ඒවා වෙනස් දේ කරයි. විට ලැයිස්තුගත ෙනොකළ, $*
සහ $@
එකම දෙයක් කරන්න. ඔවුන් සෑම 'වචනයක්ම' (සුදු පැහැති නොවන අනුක්රමය) වෙනම තර්කයක් ලෙස සලකයි. උපුටා ගත් ආකෘති ඊට වඩා බෙහෙවින් වෙනස් ය: "$*"
තර්ක ලැයිස්තුව තනි අවකාශයෙන් වෙන් කරන ලද නූලක් ලෙස "$@"
සලකන අතර විධාන රේඛාවේ නිශ්චිතව දක්වා ඇති ආකාරයටම තර්ක හරියටම වාගේ සලකයි.
"$@"
ස්ථානීය තර්ක නොමැති විට කිසිසේත් කිසිවක් නැති නොවේ; "$*"
හිස් නූලක් දක්වා විහිදේ - ඔව්, වෙනසක් ඇත, එය වටහා ගැනීම දුෂ්කර වුවද. (සම්මත නොවන) විධානය හඳුන්වා දීමෙන් පසුව වැඩි විස්තර බලන්න 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'
. කෙසේ වෙතත්, මාර්ග නාමයන්හි කිසිදු තැනක හෝ නව රේඛා හෝ ටැබ් නොමැති බව ෂෙල් වෙඩි තරයේ දිරිමත් කරයි. සම්මත යුනික්ස් ගොනු නාමවල හිස් ආදිය අඩංගු නොවන්නේ එබැවිනි.
අවකාශ සහ වෙනත් කරදරකාරී අක්ෂර අඩංගු විය හැකි ගොනු නම් සමඟ කටයුතු කිරීමේදී, ඔබ අතිශයින්ම පරෙස්සම් විය යුතු අතර, යුනික්ස් හි ප්රමිතියකින් තොර වැඩසටහනක් මට අවශ්ය බව බොහෝ කලකට පෙර මට පෙනී ගියේය. මම එය අමතන්න escape
(1.1 අනුවාදය 1989-08-23T16: 01: 45Z).
භාවිතයේ ඇති උදාහරණයක් මෙන්න escape
- SCCS පාලන පද්ධතිය සමඟ. එය ආවරණ ස්ක්රිප්ටයක් වන අතර delta
( චෙක්පත ගැන සිතන්න ) සහ
get
(සිතන්න පරීක්ෂා කරන්න ). විවිධ තර්ක, විශේෂයෙන් -y
(ඔබ වෙනස් කිරීමට හේතුව) හිස් හා නව රේඛා අඩංගු වේ. ස්ක්රිප්ට් එක 1992 සිට ආරම්භ වන බැවින් එය $(cmd ...)
අංකනය වෙනුවට බැක් කිනිතුල්ලන්
භාවිතා #!/bin/sh
කරන අතර පළමු පේළියේ භාවිතා නොකරයි .
: "@(#)$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
ඇත, එහි තර්ක එක් පේළියකට ලැයිස්තුගත කරයි (එය ඊටත් වඩා පැරණි ය: 1987-01-27T14: 35: 49 දිනැති 1.1 අනුවාදය). ස්ක්රිප්ට් නිදොස් කිරීමේදී එය වඩාත් ප්රයෝජනවත් වේ, මන්දයත් එය විධාන රේඛාවකට සම්බන්ධ කර ඇත්ත වශයෙන්ම විධානයට ලබා දෙන්නේ කුමන තර්කදැයි බැලීමට ය.
$ 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"
මෙය විකල්ප 4 ක් සකසයි, ' -new
', ' -opt
', ' and
' සහ ' arg with space
'.
]
හ්ම්, එය තරමක් දිගු පිළිතුරකි - සමහර විට exegesis යනු වඩා හොඳ යෙදුමයි. escape
ඉල්ලීම මත ලබා ගත හැකි ප්රභව කේතය (gmail dot com හි පළමු නම dot lastname වෙත විද්යුත් තැපෑලෙන් එවන්න). සඳහා වන ප්රභව කේතය 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
විධානය පමණක් ආකෘතිය string තර්කය සමඟ හිස් මාර්ගය නිෂ්පාදනය කරනු ඇත, නමුත් C වැඩසටහන් කිසිවක් නිෂ්පාදනය කරයි.