Bash / POSIX shells හි විචල්‍යයක් උපුටා දැක්වීමට අමතක වීමේ ආරක්‍ෂිත ඇඟවුම්


215

ඔබ ටික කලක් unix.stackexchange.com අනුගමනය කරන්නේ නම්, echo $varබෝර්න් / පොසික්ස් කවචවල (මෙන් ) ලැයිස්තු සන්දර්භය තුළ (මෙන් ) විචල්‍යයක් සඳහන් නොකිරීම විශේෂ අර්ථයක් ඇති බව ඔබ දැන සිටිය යුතුය. ඔබට හොඳ හේතුවක් නොමැති නම් එය නොකළ යුතුය.

එය උදාහරණ මෙතන ප්රශ්න හා ගණනාවක දීර්ඝ වශයෙන් සාකච්ඡා කරනවා (: ඇයි? Whitespace හෝ වෙනත් විශේෂ අක්ෂර මගේ ෂෙල් තිර රචනය ඇවුරුම් කරන්නේ , ? විට අවශ්ය ද්විත්ව උපුටා ඇත , එය මත glob හා භේදය සහ shell විචල්ය හා ක්රියාත්මක පුළුල් කිරීම , උදෘත එදිරිව නොකියවූ නූල් ප්‍රසාරණයට එරෙහිව)

70 දශකයේ අග භාගයේ බෝර්න් කවචය මුලින් නිකුත් වූ දා සිට එය එසේ වී ඇති අතර එය කෝර්න් කවචය ( ඩේවිඩ් කෝර්න්ගේ ලොකුම කනගාටුව (ප්‍රශ්නය # 7) ) හෝ bashවැඩි වශයෙන් කෝර්න් කවචය පිටපත් කර නැත. POSIX / Unix විසින් එය නියම කර ඇති ආකාරය.

දැන්, අපි තවමත් මෙහි පිළිතුරු ගණනාවක් දකින අතර ඉඳහිට ප්‍රසිද්ධියේ නිකුත් කරන ලද ෂෙල් කේතය පවා විචල්‍යයන් උපුටා දක්වා නොමැත. ඔබ සිතුවා මේ වන විට මිනිසුන් ඉගෙන ගනීවි කියා.

මගේ අත්දැකීම් අනුව, ප්‍රධාන වශයෙන් වර්ග 3 ක් ඔවුන්ගේ විචල්‍යයන් උපුටා දැක්වීම අතහැර දමයි:

  • ආරම්භකයින්. ඒවා සම්පුර්ණයෙන්ම නොදැනුවත්වම වාක්‍ය ඛණ්ඩයක් බව පිළිගත හැකිය. ඔවුන් දැනුවත් කිරීම මෙම වෙබ් අඩවියේ අපගේ කාර්යභාරයයි.

  • අමතක වූ මිනිසුන්.

  • නැවත නැවත මිටියකින් පසුව පවා ඒත්තු ගැන්වී නැති අය, නිසැකවම බෝර්න් ෂෙල් කතුවරයා අපගේ සියලු විචල්‍යයන් උපුටා දැක්වීමට අදහස් නොකළ බව සිතති .

මේ ආකාරයේ හැසිරීම් හා සම්බන්ධ අවදානම අප විසින් හෙළිදරව් කළහොත් සමහර විට අපට ඔවුන්ට ඒත්තු ගැන්විය හැකිය.

ඔබේ විචල්‍යයන් උපුටා දැක්වීමට ඔබට අමතක වුවහොත් සිදුවිය හැකි නරකම දෙය කුමක්ද? එය ඇත්තෙන්ම එතරම් නරකද?

අප මෙහි කතා කරන්නේ කුමන ආකාරයේ අවදානමක් ගැනද?

එය ගැටලුවක් විය හැක්කේ කුමන සන්දර්භයන් තුළද?


8
BashPitfalls යනු මා සිතන ආකාරයට ඔබ කැමති දෙයකි.
pawel7318

සිට කරුණු ලිව්වේ මම මේ ලිපිය ලියූ එම විදියක්! ස්තුතියි
mirabilos

Answers:


211

පෙරවදන

පළමුව, මම කියන්නේ ගැටලුව විසඳීමට එය නිවැරදි ක්‍රමය නොවන බවයි. එය හරියට " ඔබ මිනිසුන් murder ාතනය නොකළ යුතු නිසා වෙනත් ආකාරයකින් ඔබ හිරේට යනු ඇත " යනුවෙන් පැවසීම වැනි ය .

ඒ හා සමානව, ඔබ ඔබේ විචල්‍යය උපුටා දක්වන්නේ නැත, එසේ නොමැතිනම් ඔබ ආරක්ෂක දුර්වලතා හඳුන්වා දෙයි. ඔබ ඔබේ විචල්‍යයන් උපුටා දක්වන්නේ එය වැරදියි (නමුත් සිරගෙදරට ඇති බිය උපකාර විය හැකි නම්, එසේ නොවන්නේ මන්ද).

දුම්රියට පැන ඇති අය සඳහා කුඩා සාරාංශයක්.

බොහෝ කවච වල, විචල්‍ය ප්‍රසාරණයක් නම් නොකොට තැබීම (එය (සහ මෙම පිළිතුරේ ඉතිරි කොටස) විධාන ආදේශනයට ( `...`හෝ $(...)) අදාළ වන අතර අංක ගණිත ප්‍රසාරණයට ( $((...))හෝ $[...]) විශේෂ අර්ථයක් ඇත. එය විස්තර කිරීමට ඇති හොඳම ක්‍රමය නම් එය යම් ආකාරයක ව්‍යංග භේදයක් + ග්ලෝබ් ක්‍රියාකරුට ආයාචනා කිරීමයි.

cmd $var

වෙනත් භාෂාවකින් මෙසේ ලියනු ඇත:

cmd(glob(split($var)))

$var$IFSවිශේෂ පරාමිතිය ( බෙදීම් කොටස) සම්බන්ධ සංකීර්ණ නීතිරීතිවලට අනුව පළමුව වචන ලැයිස්තුවකට බෙදනු ලබන අතර , එම බෙදීමේ ප්‍රති result ලයක් ලෙස ඇති වන සෑම වචනයක්ම එයට ගැලපෙන ලිපිගොනු ලැයිස්තුවකට ( ගෝලීය කොටස) පුළුල් වන රටාවක් ලෙස සැලකේ. .

නිදසුනක් ලෙස, $varඅඩංගු නම් *.txt,/var/*.xmlසහ $IFS අඩංගු නම් ,, cmdතර්ක ගණනාවක් සමඟ කැඳවනු ලැබේ, පළමුවැන්න cmdසහ ඊළඟ ඒවා txt වත්මන් නාමාවලියෙහි ඇති xmlලිපිගොනු සහ ඇති ගොනු ය /var.

ඔබට cmdවචනානුසාරයෙන් තර්ක දෙකකින් ඇමතීමට අවශ්‍ය නම් cmd සහ *.txt,/var/*.xmlඔබ ලියන්නේ:

cmd "$var"

එය ඔබගේ අනෙක් හුරුපුරුදු භාෂාවෙන් වනු ඇත:

cmd($var)

කවචයක ඇති අවදානම යන්නෙන් අප අදහස් කරන්නේ කුමක්ද?

ආරක්‍ෂිත සංවේදී සන්දර්භයන් තුළ ෂෙල් ස්ක්‍රිප්ට් භාවිතා නොකළ යුතු බව කාලයාගේ ඇවෑමෙන් දැනගෙන තිබේ. නිසැකවම, හරි, විචල්‍යයක් සඳහන් නොකිරීම දෝෂයකි, නමුත් එතරම් හානියක් කළ නොහැකිද?

හොඳයි, වෙබ් සීජීඅයි සඳහා කවදාවත් ෂෙල් ස්ක්‍රිප්ට් භාවිතා නොකළ යුතු යැයි කිසිවෙකු ඔබට පැවසුවද, හෝ ස්තුතිවන්ත විය යුතු බොහෝ පද්ධති වර්තමානයේදී සෙටූයිඩ් / සෙට්ජිඩ් ෂෙල් ස්ක්‍රිප්ට් වලට ඉඩ නොදේ. ෂෙල්ෂොක් (දුරස්ථව සූරාකෑමට ලක්වන බාෂ් දෝෂය 2014 සැප්තැම්බර් මාසයේ දී සිරස්තල) අනාවරණය ෂෙල් වෙඩි තවමත් පුළුල් ඔවුන් බොහෝ විට නොවිය යුතු තැන භාවිතා කරන බව ය: පළ කළහ sudoers විධානයන් DHCP ග්රාහකයක් කොක්කෙන් පිටපත් ද,, CGIs දී විසින් (නොවේ නම් ලෙස ) setuid විධාන ...

සමහර විට නොදැනුවත්ව. උදාහරණයක් ලෙස system('cmd $PATH_INFO') දී php/ perl/ pythonCGI විධානාවලිය විධාන රේඛාව (සඳහන් නොකලත් බව අර්ථ නිරූපණය කිරීමට තිබෙන shell පහ කරන්නේ cmdම ෂෙල් තිර රචනය සහ එහි කර්තෘ විය හැක එය ලබන්නේ CGI කැඳවා කිරීමට අපේක්ෂා කවදාවත් ඇත).

වරප්‍රසාද ඉහළ නැංවීමේ මාර්ගයක් ඇති විට ඔබට අවදානමක් තිබේ, එනම් යමෙකුට (ඔහුට පහර දෙන්නා යැයි කියමු ) ඔහු අදහස් නොකරන දෙයක් කිරීමට හැකි වේ.

නොවරදවාම එයින් අදහස් කරන්නේ දත්ත සපයන ප්‍රහාරකයා , වරප්‍රසාදිත පරිශීලකයෙකු / ක්‍රියාවලියක් විසින් දත්ත සැකසීම, එය නොදැනුවත්වම එය නොකළ යුතු දෙයක් කරන අතර, බොහෝ විට එය දෝෂයක් නිසා ය.

මූලික වශයෙන්, ඔබේ දෝෂ සහිත කේතය ප්‍රහාරකයාගේ පාලනය යටතේ දත්ත සැකසීමේදී ඔබට ගැටළුවක් ඇත.

දැන්, එම දත්ත පැමිණෙන්නේ කොහෙන්ද යන්න සැමවිටම පැහැදිලිව පෙනෙන්නට නැති අතර, විශ්වාසනීය නොවන දත්ත සැකසීමට ඔබේ කේතය කවදා හෝ ලැබේදැයි කීමට බොහෝ විට අපහසුය.

විචල්‍යයන් සම්බන්ධයෙන් ගත් කල, සීජීඅයි ස්ක්‍රිප්ටයක් සම්බන්ධයෙන් ගත් කල, දත්ත පැහැදිලිවම සීජීඅයි ජීඊටී / පෝස්ට් පරාමිතීන් සහ කුකීස්, පථය, ධාරක ... පරාමිතීන් ය.

සෙටූයිඩ් ස්ක්‍රිප්ටයක් සඳහා (එක් පරිශීලකයෙකු වෙනත් අයෙකු විසින් ක්‍රියාත්මක කරන විට), එය තර්ක හෝ පරිසර විචල්‍යයන් වේ.

තවත් ඉතා සුලභ දෛශිකයක් වන්නේ ගොනු නම් ය. ඔබ නාමාවලියකින් ගොනු ලැයිස්තුවක් ලබා ගන්නේ නම්, ප්‍රහාරකයා විසින් එහි ලිපිගොනු රෝපණය කර ඇති බව පෙනේ.

මේ සම්බන්ධයෙන්, අන්තර්ක්‍රියාකාරී කවචයක කඩිනමින් වුවද, ඔබ අවදානමට ලක්විය හැකිය (ලිපිගොනු සැකසීමේදී /tmpහෝ ~/tmp උදාහරණයක් ලෙස).

පවා ~/.bashrcඅවදානමට ලක්විය හැකිය (නිදසුනක් ලෙස, සේවාදායකයාගේ පාලනය යටතේ සමහර විචල්‍යයන් සහිත සේවාදායක යෙදවීම් වලදී ක්‍රියාත්මක කිරීමට සමාන වූ bashවිට එය අර්ථ නිරූපණය කරනු ඇත ).sshForcedCommandgit

දැන්, විශ්වාසදායක නොවන දත්ත සැකසීම සඳහා ස්ක්‍රිප්ට් එකක් කෙලින්ම කැඳවනු නොලැබේ, නමුත් එය වෙනත් විධානයක් මගින් කැඳවනු ලැබේ. නැතහොත් ඔබගේ වැරදි කේතය පිටපත් වලට පිටපත් කළ හැකිය (ඔබ විසින් වසර 3 ක් පහළට හෝ ඔබේ සගයකුට). ඔබේ කේතයේ පිටපත් අවසන් වන්නේ කොතැනින්දැයි ඔබ කිසි විටෙකත් නොදන්නා බැවින් එය විශේෂයෙන් විවේචනාත්මක වන එක් ප්‍රශ්නෝත්තර වෙබ් අඩවි වල පිළිතුරු ඇත.

ව්‍යාපාරයට බැස; එය කෙතරම් නරකද?

විචල්ය (හෝ විධාන ආදේශනය) නම් නොකොට තැබීම ෂෙල් කේතය හා සම්බන්ධ ආරක්ෂක දුර්වලතා වල අංක එකේ ප්රභවය වේ. අර්ධ වශයෙන් එම දෝෂ බොහෝ විට අනාරක්ෂිතභාවයට පරිවර්තනය වන අතර, නොකියවූ විචල්‍යයන් දැකීම සාමාන්‍ය දෙයක් වන බැවිනි.

ඇත්ත වශයෙන්ම, ෂෙල් කේතයේ ඇති දුර්වලතා සොයන විට, කළ යුතු පළමු දෙය නම් නොකල විචල්‍යයන් සොයා බැලීමයි. හඳුනා ගැනීම පහසුය, බොහෝ විට හොඳ අපේක්ෂකයෙකු, සාමාන්‍යයෙන් ප්‍රහාරකයා විසින් පාලනය කරන ලද දත්ත වෙත ආපසු යාම පහසුය.

නොකියවූ විචල්‍යයක් අවදානමට ලක්විය හැකි ආකාර ගණනක් ඇත. මම මෙහි පොදු ප්‍රවණතා කිහිපයක් දෙන්නම්.

තොරතුරු අනාවරණය කිරීම

බෙදීම් කොටස නිසා බොහෝ අය නම් නොකල විචල්‍යයන් හා සම්බන්ධ දෝෂ වලට ගොදුරු වනු ඇත (නිදසුනක් ලෙස, වර්තමානයේ ලිපිගොනු වල නම් වල අවකාශයන් තිබීම සාමාන්‍ය දෙයක් වන අතර අවකාශය IFS හි පෙරනිමි අගයේ පවතී). බොහෝ අය ගෝලීය කොටස නොසලකා හරිනු ඇත . මෙම glob කොටසක් අවම වශයෙන් ලෙස දරුණු ලෙස ය භේදය කොටසක්.

අනාරක්‍ෂිත බාහිර ආදානය මත ග්ලෝබ් කිරීම යනු ඕනෑම නාමාවලියක අන්තර්ගතය කියවීමට ප්‍රහාරකයාට හැකි වේ.

තුළ:

echo You entered: $unsanitised_external_input

$unsanitised_external_inputඅඩංගු නම් /*, එයින් අදහස් කරන්නේ ප්‍රහාරකයාට අන්තර්ගතය දැකිය හැකි බවයි /. ලොකු දෙයක් නැහැ. /home/*යන්ත්‍රයේ පරිශීලක නාම ලැයිස්තුවක් /tmp/*, /home/*/.forwardවෙනත් භයානක භාවිතයන් පිළිබඳ ඉඟි /etc/rc*/*සඳහා, සක්‍රීය සේවාවන් සඳහා එය ලබා දෙන නමුත් එය වඩාත් සිත්ගන්නා සුළු වේ ... ඒවා තනි තනිව නම් කිරීම අවශ්‍ය නොවේ. වටිනාකමකින් /* /*/* /*/*/*...මුළු ගොනු පද්ධතියම ලැයිස්තු ගත වේ.

සේවා දුර්වලතා ප්‍රතික්ෂේප කිරීම.

පෙර නඩුව ටිකක් දුරින් ගෙන අපට DoS එකක් තිබේ.

ඇත්ත වශයෙන්ම, ලැයිස්තුගත සන්දර්භය තුළ සනීපාරක්ෂක නොවන ආදානය සහිත නම් නොකල ඕනෑම විචල්‍යයක් අවම වශයෙන් DoS අවදානමක් ඇත.

විශේෂ expert ෂෙල් ස්ක්‍රිප්ටර්වරු පවා මෙවැනි දේ උපුටා දැක්වීමට අමතක කරති:

#! /bin/sh -
: ${QUERYSTRING=$1}

:no-op විධානයයි. වැරදි විය හැකි දේ කුමක්ද?

බව අනුයුක්ත කිරීමට අදහස් කරනවා $1කිරීමට $QUERYSTRINGනම් $QUERYSTRING ශූන්යය විය. විධාන රේඛාවෙන් CGI ස්ක්‍රිප්ට් එකක් කැඳවිය හැකි ඉක්මන්ම ක්‍රමයකි.

එය $QUERYSTRINGතවමත් පුළුල් වී ඇති අතර එය උපුටා දක්වා නොමැති නිසා, භේදය + ග්ලෝබ් ක්‍රියාකරු ආයාචනා කරනු ලැබේ.

දැන්, පුළුල් කිරීම සඳහා විශේෂයෙන් මිල අධික වන ග්ලෝබ් කිහිපයක් තිබේ. මෙම /*/*/*/*පහළ මට්ටම් 4 බහලුම ලැයිස්තුගත අදහස් ලෙස එක් නරක තරම් වේ. තැටිය සහ CPU ක්‍රියාකාරකම් වලට අමතරව, එයින් අදහස් වන්නේ දස දහස් ගණනක් ගොනු මාර්ග ගබඩා කිරීමයි (අවම සේවාදායක VM එකක 40k, මෙහි 10k ඩිරෙක්ටරි).

දැන් /*/*/*/*/../../../../*/*/*/*අදහස් කරන්නේ 40k x 10k වන /*/*/*/*/../../../../*/*/*/*/../../../../*/*/*/*අතර බලවත්ම යන්ත්‍රය පවා දණහිසට ගෙන ඒමට එය ප්‍රමාණවත් වේ.

එය ඔබම අත්හදා බලන්න (ඔබේ යන්ත්‍රය බිඳ වැටීමට හෝ එල්ලීමට සූදානම්ව සිටියද):

a='/*/*/*/*/../../../../*/*/*/*/../../../../*/*/*/*' sh -c ': ${a=foo}'

ඇත්ත වශයෙන්ම, කේතය නම්:

echo $QUERYSTRING > /some/file

එවිට ඔබට තැටිය පිරවිය හැකිය.

Shell cgi හෝ bash cgi හෝ ksh cgi හි ගූගල් සෙවුමක් කරන්න , එවිට ඔබට ෂෙල් වෙඩි වලින් CGI ලිවිය යුතු ආකාරය පෙන්වන පිටු කිහිපයක් හමුවනු ඇත. පරාමිතීන් සැකසෙන ඒවායින් අඩක් අවදානමට ලක්වන ආකාරය සැලකිල්ලට ගන්න.

පවා ඩේවිඩ් Korn ම එක් (මෙම කුකිය හැසිරවීමේ දී පෙනුම) ඇති ඉඩකඩ වැඩි ය.

අත්තනෝමතික කේත ක්‍රියාත්මක කිරීමේ දුර්වලතා දක්වා

අත්තනෝමතික කේත ක්‍රියාත්මක කිරීම නරකම ආකාරයේ අවදානමකි, මන්ද ප්‍රහාරකයාට ඕනෑම විධානයක් ක්‍රියාත්මක කළ හැකි නම් , ඔහු කළ හැකි දේට සීමාවක් නොමැත.

සාමාන්‍යයෙන් ඒවාට බෙදී යන කොටස එයයි . එය බෙදීමෙන් ප්‍රති results ල ලැබෙන්නේ එක් අයෙකු පමණක් බලාපොරොත්තු වූ විට විධාන වෙත යැවීම සඳහා තර්ක කිහිපයක් ය. ඒවායින් පළමුවැන්න අපේක්ෂිත සන්දර්භය තුළ භාවිතා කරනු ඇති අතර අනෙක් ඒවා වෙනස් සන්දර්භයක පවතිනු ඇත. උදාහරණයක් සමඟ වඩා හොඳ:

awk -v foo=$external_input '$2 == foo'

මෙන්න, අභිප්රාය වූයේ $external_inputෂෙල් විචල්යයේ අන්තර්ගතය foo awkවිචල්යයට පැවරීමයි.

දැන්:

$ external_input='x BEGIN{system("uname")}'
$ awk -v foo=$external_input '$2 == foo'
Linux

බෙදීමේ ප්‍රති result ලයක් ලෙස දෙවන වචනය $external_input පවරා නැති fooනමුත් awkකේතයක් ලෙස සලකනු ලැබේ (මෙහි අත්තනෝමතික විධානයක් ක්‍රියාත්මක කරයි :) uname.

බව (අනෙකුත් විධානයන් ක්රියාත්මක කළ හැකි විධාන සඳහා විශේෂයෙන්ම ප්රශ්නයක් awk, env, sed, (GNU එකක්) perl, find...) යනු GNU ප්රභේද්යයන් විශේෂයෙන් සමග (තර්ක පසු විකල්ප පිලිගන්නවා). සමහර විට, ඔබ වැනි වෙනත් අය ක්රියාත්මක කිරීමට හැකි විය සැකකරු විධාන නො ksh, bashහෝ zshගේ [හෝ printf...

for file in *; do
  [ -f $file ] || continue
  something-that-would-be-dangerous-if-$file-were-a-directory
done

අප නමින් නාමාවලියක් නිර්මාණය කරන්නේ නම් x -o yes, පරීක්ෂණය ධනාත්මක බවට පත්වේ, මන්ද එය අප ඇගයීමට ලක් කරන සම්පූර්ණයෙන්ම වෙනස් කොන්දේසි සහිත ප්‍රකාශනයකි.

නරකම දෙය නම්, x -a a[0$(uname>&2)] -gt 1අවම වශයෙන් සියලු ksh ක්‍රියාත්මක කිරීම් සහිතව ( sh බොහෝ වාණිජ ඒකක සහ සමහර BSD ඇතුළත්) ගොනුවක් නිර්මාණය කරන්නේ නම් , එය ක්‍රියාත්මක uname වන්නේ එම කවචයන් [විධානයේ සංඛ්‍යාත්මක සංසන්දනාත්මක ක්‍රියාකරුවන් මත ගණිතමය ඇගයීමක් සිදු කරන බැවිනි .

$ touch x 'x -a a[0$(uname>&2)] -gt 1'
$ ksh -c 'for f in *; do [ -f $f ]; done'
Linux

සමග එකම bashවැනි ගොනු සඳහා x -a -v a[0$(uname>&2)].

ඇත්ත වශයෙන්ම, ඔවුන්ට අත්තනෝමතික ලෙස ක්‍රියාත්මක කිරීමට නොහැකි නම්, ප්‍රහාරකයා අඩු හානියක් සඳහා විසඳුම් ලබා දිය හැකිය (එය අත්තනෝමතික ලෙස ක්‍රියාත්මක කිරීමට උපකාරී වේ). ලිපිගොනු ලිවීමට හෝ අවසර වෙනස් කිරීමට, හිමිකාරිත්වය හෝ ප්‍රධාන හෝ අතුරු ආබාධ ඇති ඕනෑම විධානයක් සූරාකෑමට ලක්විය හැකිය.

සෑම ආකාරයකම ලිපිගොනු නාම වලින් කළ හැකිය.

$ touch -- '-R ..'
$ for file in *; do [ -f "$file" ] && chmod +w $file; done

ඔබ ..ලිවිය හැකි (GNU සමඟ පුනරාවර්තන ලෙස chmod) සෑදීම අවසන් කරයි .

වැනි ප්‍රසිද්ධියේ ලිවිය හැකි ප්‍රදේශවල ලිපිගොනු ස්වයංක්‍රීයව සැකසීමේ පිටපත් /tmpඉතා ප්‍රවේශමෙන් ලිවිය යුතුය.

මොකද කරන්නේ [ $# -gt 1 ]

එය මා කෝපයට පත් කරන දෙයක්. සමහර පුද්ගලයින්ට උපුටා දැක්වීම් මඟ හැරිය හැකිදැයි තීරණය කිරීම සඳහා විශේෂිත ප්‍රසාරණයක් ගැටළු සහගත විය හැකිදැයි කල්පනා කිරීමේ සියලු කරදර පහව යයි.

එය කියන්නාක් මෙනි. හේයි, එය $#භේදය + ග්ලෝබ් ක්‍රියාකරුට යටත් විය නොහැකි බව පෙනේ , අපි ෂෙල් එකෙන් බෙදීමට + ග්ලෝබ් කරන්නැයි ඉල්ලා සිටිමු . නැතහොත් හේයි, දෝෂය ඇතිවීමට ඉඩක් නොමැති නිසා වැරදි කේතයක් ලියමු .

දැන් එය කොතරම් අපහසුද? හරි, $#(හෝ $!, $?හෝ ඕනෑම අංක ගණිත ආදේශකයක්) අඩංගු විය හැක්කේ ඉලක්කම් (හෝ -සමහරක් සඳහා) නිසා ගෝලීය කොටස ඉවරයි . සඳහා භේදය නමුත් යමක් කිරීමට කොටසක්, අපට අවශ්ය සියලු සඳහා $IFSඉලක්කම් (හෝ අඩංගු -).

සමහර ෂෙල් වෙඩි සමඟ, $IFSපරිසරයෙන් උරුම විය හැකි නමුත් පරිසරය ආරක්ෂිත නොවේ නම්, එය කෙසේ හෝ අවසන් වේ.

දැන් ඔබ මෙවැනි ශ්‍රිතයක් ලියන්නේ නම්:

my_function() {
  [ $# -eq 2 ] || return
  ...
}

එයින් අදහස් කරන්නේ ඔබේ ශ්‍රිතයේ හැසිරීම එය හැඳින්වෙන සන්දර්භය මත රඳා පවතින බවයි. නැතහොත් වෙනත් වචන වලින් කිවහොත්, $IFS එය සඳහා යෙදවුම් වලින් එකක් බවට පත්වේ. නිශ්චිතවම කිවහොත්, ඔබ ඔබේ කාර්යය සඳහා API ප්‍රලේඛනය ලියන විට, එය මෙවැනි දෙයක් විය යුතුය:

# my_function
#   inputs:
#     $1: source directory
#     $2: destination directory
#   $IFS: used to split $#, expected not to contain digits...

ඔබේ ශ්‍රිතයට කේත ඇමතීමෙන් $IFSඉලක්කම් අඩංගු නොවන බවට වග බලා ගත යුතුය. ඒ සියල්ලම ද්වි-උපුටා දැක්වීමේ අකුරු 2 ටයිප් කිරීමට ඔබට හැඟී නැති නිසාය.

දැන්, එම [ $# -eq 2 ]දෝෂය අවදානමට ලක්වීමට නම්, ඔබට කෙසේ හෝ ප්‍රහාරකයාගේ$IFS පාලනය යටතට පත්වීමේ වටිනාකම අවශ්‍ය වේ. පෙනෙන ආකාරයට, ප්‍රහාරකයා වෙනත් දෝෂයක් ගසාකෑමට සමත් වුවහොත් එය සාමාන්‍යයෙන් සිදු නොවේ .

එය නොඇසූ දෙයක් නොවේ. පොදු කරුණක් වන්නේ ගණිත ප්‍රකාශනයේ දත්ත භාවිතා කිරීමට පෙර දත්ත සනීපාරක්ෂාව කිරීමට මිනිසුන්ට අමතක වීමයි. සමහර ෂෙල් වෙඩි තුළ අත්තනෝමතික කේත ක්‍රියාත්මක කිරීමට එයට ඉඩ දිය හැකි බව අපි දැනටමත් දැක ඇත්තෙමු, නමුත් ඒ සියල්ලෙහිම, ප්‍රහාරකයාට ඕනෑම විචල්‍යයකට පූර්ණ සංඛ්‍යාවක් ලබා දීමට ඉඩ දෙයි .

උදාහරණයක් වශයෙන්:

n=$(($1 + 1))
if [ $# -gt 2 ]; then
  echo >&2 "Too many arguments"
  exit 1
fi

හා සමග $1වටිනාකම (IFS=-1234567890), එම අංක ගණිතමය ඇගයීම සැකසුම් IFS පැත්තේ බලපාන අතර ඊළඟ [ විධානය සඳහා වන චෙක්පත, ඉන් අදහස් වන්නේ අසමත් බොහෝ args අතුරු මාර්ගයක් ඇත.

භේදය + ග්ලෝබ් ක්‍රියාකරු ආයාචනා නොකළ විට කුමක් කළ යුතුද?

විචල්යයන් සහ වෙනත් පුළුල් කිරීම් වටා මිල ගණන් අවශ්ය වන තවත් අවස්ථාවක් තිබේ: එය රටාවක් ලෙස භාවිතා කරන විට.

[[ $a = $b ]]   # a `ksh` construct also supported by `bash`
case $a in ($b) ...; esac

එක $aහා සමානද යන්න පරීක්ෂා නොකරන්න $b(හැර zsh) නමුත් $aරටාවට ගැලපෙන්නේ නම් $b. ඔබ උපුටා ගැනීමට අවශ්ය $bඔබ නූල් ලෙස සංසන්දනය කිරීමට අවශ්ය නම් (එකම දෙයක් ගැන "${a#$b}"හෝ "${a%$b}"හෝ "${a##*$b*}"එහිදී $bඑය රටාවක් ලෙස ගත යුතු නෑ නම් උපුටා ගත යුතුය).

කුමක්ද යන්න ප්රකාශ වේ [[ $a = $b ]]අවස්ථාවන්හීදී සැබෑ ආපසු හැක $aවෙනස් වේ $b(උදාහරණයක් ලෙස විට $aanythingසහ $b*) හෝ ඔවුන් සමාන (දෙකම, උදාහරණයක් විට බොරු ආපසු හැක $aසහ $b[a]).

එය ආරක්ෂිත අවදානමක් ඇති කළ හැකිද? ඔව්, ඕනෑම දෝෂයක් වගේ. මෙන්න, ප්‍රහාරකයාට ඔබගේ ස්ක්‍රිප්ටයේ තාර්කික කේත ප්‍රවාහය වෙනස් කිරීමට සහ / හෝ ඔබේ ස්ක්‍රිප්ට් කරන උපකල්පන බිඳ දැමිය හැකිය. උදාහරණයක් ලෙස, වැනි කේතයක් සමඟ:

if [[ $1 = $2 ]]; then
   echo >&2 '$1 and $2 cannot be the same or damage will incur'
   exit 1
fi

පහර දෙන්නාට චෙක්පත මඟ හැරිය හැක '[a]' '[a]'.

දැන්, එම රටා ගැලපීම හෝ භේදය + ග්ලෝබ් ක්‍රියාකරු අදාළ නොවේ නම්, විචල්‍යයක් නොකියවා තැබීමේ අන්තරාය කුමක්ද?

මා ලියන බව පිළිගත යුතුය:

a=$b
case $a in...

එහිදී, උපුටා දැක්වීම හානියක් නොවන නමුත් දැඩි ලෙස අවශ්‍ය නොවේ.

කෙසේ වෙතත්, එම අවස්ථා වලදී උපුටා දැක්වීම් මඟ හැරීමේ එක් අතුරු effect ලයක් නම් (නිදසුනක් ලෙස ප්‍රශ්නෝත්තර පිළිතුරු වල) එය ආරම්භකයින්ට වැරදි පණිවිඩයක් යැවිය හැකි ය: විචල්‍යයන් උපුටා දැක්වීම නොකිරීම හරි ය .

නිදසුනක් ලෙස, ඔවුන් සිතීමට පටන් ගත හැකිය a=$b, හරි නම් , එය එසේම export a=$bවනු ඇත ( එය බොහෝ ෂෙල් වෙඩි වල නොමැති බැවින් එය exportවිධානයට තර්ක කරන බැවින් ලැයිස්තු සන්දර්භය තුළ) හෝ env a=$b.

කුමක් ගැනද zsh?

zshඑම නිර්මාණයේ බොහෝ අමුතුකම් නිවැරදි කර ඇත. දී zsh(අවම වශයෙන් විට sh / ksh මාත කර නැති), ඔබට අවශ්ය නම් පැලෙන හෝ globbing , හෝ රටාව ගැලපෙන , ඔබ සතුව ඒ සඳහා ඉල්ලුම් කිරීමට ඇති: $=varභේදය, සහ $~varglob හෝ ලෙස සැලකිය යුතුයි විචල්ය අන්තර්ගතය සඳහා රටාවක්.

කෙසේ වෙතත්, බෙදීම (නමුත් ග්ලෝබ් කිරීම නොවේ) තවමත් ව්‍යංගයෙන් සිදු කරනුයේ නම් නොකල විධාන ආදේශනය මත ය (මෙන් echo $(cmd)).

එසේම, විචල්‍යය උපුටා නොකිරීමේ සමහර විට අනවශ්‍ය අතුරු ආබාධයක් වන්නේ හිස් ඉවත් කිරීමයි. zshග්ලෝබ් කිරීම සම්පූර්ණයෙන්ම (සමග set -f) අක්‍රීය කිරීමෙන් සහ (සමඟ IFS='') බෙදීමෙන් ඔබට වෙනත් ෂෙල් වෙඩි වලින් ලබා ගත හැකි දේට මෙම හැසිරීම සමාන වේ . තවමත්, තුළ:

cmd $var

බෙදීම් + ග්ලෝබ් එකක් නොතිබෙනු ඇත , නමුත් $varහිස් නම් , එක් හිස් තර්කයක් ලබා ගැනීම වෙනුවට, cmdකිසිදු තර්කයක් නොලැබේ.

එය දෝෂ ඇති කළ හැකිය (පැහැදිලිව පෙනෙන පරිදි [ -n $var ]). එය ස්ක්‍රිප්ට් එකක අපේක්ෂාවන් සහ උපකල්පන බිඳ දැමිය හැකි අතර අනාරක්ෂිතභාවයට හේතු විය හැක, නමුත් මට දැන් එතරම් දුරට ලබා ගත නොහැකි උදාහරණයක් ඉදිරිපත් කළ නොහැක).

ඔබට භේදය + ග්ලෝබ් ක්‍රියාකරු අවශ්‍ය වූ විට කුමක් කළ යුතුද?

ඔව්, එය සාමාන්‍යයෙන් ඔබේ විචල්‍යය නොසලකා හැරීමට අවශ්‍ය විටය. නමුත් ඔබ එය භාවිතා කිරීමට පෙර ඔබේ භේදය හා ග්ලෝබ් ක්‍රියාකරුවන් නිවැරදිව සුසර කරන බවට වග බලා ගත යුතුය. ඔබට අවශ්‍ය වන්නේ බෙදීම් කොටස මිස ග්ලෝබ් කොටස නොවේ (බොහෝ විට එය එසේ වේ), එවිට ඔබට ග්ලෝබින් ( set -o noglob/ set -f) අක්‍රීය කර නිවැරදි කළ $IFSයුතුය. එසේ නොමැතිනම් ඔබ ද අවදානම් ඇති කරයි (ඉහත සඳහන් කළ ඩේවිඩ් කෝර්න්ගේ සීජීඅයි උදාහරණය වැනි).

නිගමනය

කෙටියෙන් කිවහොත්, විචල්යයක් (හෝ විධාන ආදේශනය හෝ අංක ගණිත විස්තාරණය) ෂෙල් වෙඩි වල සටහන් නොකිරීම සැබවින්ම භයානක විය හැකිය, විශේෂයෙන් වැරදි සන්දර්භයන් තුළ සිදු කරන විට, එම වැරදි සන්දර්භයන් මොනවාදැයි දැන ගැනීම ඉතා අපහසුය.

එය නරක පුරුද්දක් ලෙස සැලකීමට එක් හේතුවකි .

මෙතෙක් කියවීමට ස්තූතියි. එය ඔබේ හිසට ඉහළින් ගියහොත්, කරදර නොවන්න. සෑම කෙනෙකුම තම කේතය ලිවීමේදී එය ලිවීමේ සියලු ඇඟවුම් තේරුම් ගනී යැයි අපේක්ෂා කළ නොහැකිය. අපට හොඳ පුහුණු නිර්දේශයන් ඇත්තේ එබැවිනි , එබැවින් අවශ්‍යතාවය තේරුම් නොගෙන ඒවා අනුගමනය කළ හැකිය.

(එය තවම පැහැදිලි නැතිනම් කරුණාකර ආරක්ෂක සංවේදී කේත ෂෙල් වෙඩි වලින් ලිවීමෙන් වළකින්න).

හා මෙම වෙබ් අඩවිය ඔබේ පිළිතුරු ඔබේ විචල්ය උපුටා කරුණාකරලා!


ksh93සහ pdkshසහ ව්‍යුත්පන්නයන්හි, ග්ලෝබින් අක්‍රීය කර නොමැති නම් වරහන් ප්‍රසාරණය ද සිදු කරනු ලැබේ ( ksh93ksh93u + දක්වා වූ අනුවාද වලදී, braceexpandවිකල්පය අක්‍රිය වූ විට පවා ).


සමග, එම සටහන [[, සැසඳීම් පමණක් ආර් උපුටා කළ යුතුය:if [[ $1 = "$2" ]]; then
mirabilos

2
@mirabilos, ඔව්, නමුත් LHS අවශ්ය නොවන නොවේ උපුටා කිරීමට, ඒ නිසා අපි දැනුවත් තීන්දුවක් ගත කිරීමට භාවිතා කරන්නේ නම් එහි එය උපුටා (නොකරන ලෙස කිසිදු හේතුවක් තියෙනවා උපුටා පෙරනිමියෙන් එය කිරීමට වඩාත් සංවේදී දෙයක් බව පෙනේ ලෙස ). පළමු අක්‍ෂරය අවකාශය නොමැති නම් [[ $* = "$var" ]]එය සමාන නොවන බව සලකන්න (එසේම හිස් නම් එය සමාන වන්නේ කුමක් දැයි මට විශ්වාස නැත , මම දෝෂයක් මතු කළ යුතුද?)). [[ "$*" = "$var" ]]$IFSbashmksh$IFS$*
ස්ටෙෆාන් චසෙලාස්

1
ඔව්, ඔබට එහි පෙරනිමියෙන් උපුටා දැක්විය හැකිය. කරුණාකර ක්ෂේත්‍ර බෙදීම් පිළිබඳ තවත් දෝෂ කිසිවක් නොකරන්න, මෙය නැවත ඇගයීමට පෙර මා දන්නා අය (ඔබෙන් සහ වෙනත් අයගෙන්) පළමුව නිවැරදි කළ යුතුව ඇත.
මිරබිලෝස්

2
Ar බාර්මාර්, ඔබ අදහස් කළේ යැයි සිතමු, foo='bar; rm *'නැත, එසේ නොවේ, කෙසේ වෙතත් එය තොරතුරු අනාවරණය කිරීමක් ලෙස සැලකිය හැකි වත්මන් නාමාවලියෙහි අන්තර්ගතය ලැයිස්තුගත කරයි. print $fooතුළ ksh93( එම අඩුපාඩු සමහරක් printආදේශ කිරීම කොහේද echo) කේත එන්නත් කිරීමේ අවදානමක් ඇතත් (නිදසුනක් ලෙස foo='-f%.0d z[0$(uname>&2)]') (ඔබට ඇත්ත වශයෙන්ම අවශ්‍යය print -r -- "$foo". echo "$foo"තවමත් වැරදියි, නිවැරදි කළ නොහැකි ය (සාමාන්‍යයෙන් අඩු හානිකර වුවද).
ස්ටෙෆාන් චසෙලාස්

3
මම දක්ෂ විශේෂ expert යෙක් නොවෙමි, නමුත් මම දශකයකට වැඩි කාලයක් තිස්සේ එහි කේතනය කර ඇත. මම උපුටා දැක්වීම් ගොඩක් භාවිතා කළෙමි, නමුත් ප්‍රධාන වශයෙන් කාවැද්දූ හිස් හැසිරවීමට. දැන්, මම ඒවා තවත් බොහෝ දේ භාවිතා කරමි! සියළුම සියුම් කරුණු අවශෝෂණය කර ගැනීම ටිකක් පහසු කිරීම සඳහා යමෙකු මෙම පිළිතුර පුළුල් කළහොත් හොඳයි. මට එය ගොඩක් ලැබුණා, නමුත් මටත් බොහෝ දේ මග හැරුණි. එය දැනටමත් දිගු සටහනකි, නමුත් මට ඉගෙන ගැනීමට තවත් බොහෝ දේ මෙහි ඇති බව මම දනිමි. ස්තූතියි!
ජෝ

35

[විසින් ජාතිය මේ පිළිතුර විසින් CAS .]

නමුත් කුමක් නම්…?

නමුත් මගේ ස්ක්‍රිප්ට් භාවිතා කිරීමට පෙර දන්නා අගයකට විචල්‍යයක් සකසන්නේ නම් කුමක් කළ යුතුද? විශේෂයෙන්, එය විචල්‍යයන් දෙකක් හෝ වැඩි ගණනකට විචල්‍යයක් සකසන්නේ නම් කුමක් කළ යුතුද (නමුත් එය සැමවිටම එය දන්නා දෙයකට සකසයි), සහ කිසිදු අගයක අවකාශය හෝ ගෝලීය අක්ෂර අඩංගු නොවේද? එම අවස්ථාවේ දී උපුටා දැක්වීම් නොමැතිව එය භාවිතා කිරීම ආරක්ෂිත නොවේ ද ?

විය හැකි අගයන්ගෙන් එකක් හිස් නූල නම්, මම “ඉවත් කිරීම හිස් කිරීම” මත රඳා පවතී නම් කුමක් කළ යුතුද? එනම්, විචල්‍යයේ හිස් නූලක් තිබේ නම්, මගේ විධානයෙහි හිස් නූල ලබා ගැනීමට මට අවශ්‍ය නැත; මට කිසිවක් ලබා ගැනීමට අවශ්‍ය නැත. උදාහරණයක් වශයෙන්,

නම්  කොන්දේසියක්
එවිට
    නොසලකා හැරීම = "- i"
නැතිනම්
    නොසලකා හැරීම = ""
fi
                                        # ඉහත විධානයන්හි උපුටා දැක්වීම් දැඩි ලෙස අවශ්‍ය නොවන බව සලකන්න . 
grep other නොසලකා හරින්න   other_ grep _args

මට කියන්න බැහැ ; හිස් නූල නම් එය අසාර්ථක වනු ඇත .grep "$ignorecase" other_grep_args$ignorecase

ප්‍රතිචාරය:

අනෙක් පිළිතුරෙහි සාකච්ඡා කර ඇති පරිදි, IFSa -හෝ a අඩංගු නම් මෙය තවමත් අසාර්ථක වනු ඇත i. IFSඔබේ විචල්‍යයේ කිසිදු අක්ෂරයක් අඩංගු නොවන බව ඔබ සහතික කර ඇත්නම් (සහ ඔබේ විචල්‍යයේ කිසිදු ගෝලීය අක්ෂර අඩංගු නොවන බව ඔබට විශ්වාසයි), එවිට මෙය බොහෝ විට ආරක්ෂිත වේ.

නමුත් ආරක්ෂිත ක්‍රමයක් තිබේ (එය තරමක් කැත සහ තරමක් නොදැනුවත්ව වුවද): භාවිතා කරන්න ${ignorecase:+"$ignorecase"}. සිට මෙම POSIX ෂෙල් අණ භාෂා පිරිවිතර යටතේ  2.6.2 පරාමිති පුළුල් කිරීම ,

${parameter:+[word]}

    විකල්ප අගය භාවිතා කරන්න.   නම් parameterශූන්යය හෝ ශූන්ය වේ, ශුන්ය ආදේශ කළ යුතු ය එසේ word නොමැතිනම් (හෝ හිස් නූලක් wordමඟ හැරී ඇත්නම් ) පුළුල් කිරීම ආදේශ කළ යුතුය.

මෙහි ඇති උපක්‍රමය, එය වැනි, අප භාවිතා ignorecaseකරන්නේ parameter සහ "$ignorecase"ලෙස ය word. ඒ ${ignorecase:+"$ignorecase"}කියන්නේ

නම් $ignorecaseශූන්යය හෝ ශූන්ය වේ (එනම්, හිස්), ශුන්ය (එනම්, ලැයිස්තුගත ෙනොකළ කිසිවක් ) ආදේශ කළ යුතු ය එසේ නොමැතිනම් පුළුල් කිරීම "$ignorecase"ආදේශ කළ යුතුය.

මෙය අපට යාමට අවශ්‍ය තැන අපට ලබා දෙයි: විචල්‍යය හිස් නූලට සකසා ඇත්නම්, එය “ඉවත් කරනු ලැබේ” (මෙම සමස්ත, කැටි ගැසුණු ප්‍රකාශනය කිසිසේත් තක්සේරු නොකරනු ඇත - හිස් නූලක්වත් නොවේ), සහ විචල්‍යයට නොඑසේ නම් -empty අගය, අපට එම අගය ලැබෙනු ඇත.


නමුත් කුමක් නම්…?

නමුත් මට අවශ්‍ය / අවශ්‍ය වචන විචල්‍යයක් තිබේ නම් කුමක් කළ යුතුද? . හතරේ පහර.
ප්රාදේශීය සභා මම තවමත් අතහරී ඉවත් අවශ්යය.)

උදාහරණයක් වශයෙන්,

යම් කොන්දේසියක් නම්
එවිට
    නිර්ණායක = "- වර්ගය f"
නැතිනම්
    නිර්ණායක = ""
fisome_other_condition 
නම්
එවිට
    නිර්ණායක = "$ නිර්ණායක -mtime +42"
fi
"$ start_directory" find නිර්ණායක   වෙනත්_ආරෑම් සොයා ගන්න

ප්‍රතිචාරය:

මෙය භාවිතා කිරීම සඳහා අවස්ථාවක් යැයි ඔබට සිතෙනු evalඇත.  නොමැත! evalමෙහි   භාවිතා කිරීම ගැන සිතීමට පවා පෙළඹවීමට එරෙහි වන්න .

නැවතත්, IFSඔබේ විචල්‍යයේ කිසිදු අක්ෂරයක් අඩංගු නොවන බවට ඔබ සහතික කර ඇත්නම් (ඔබට ගෞරව කිරීමට අවශ්‍ය අවකාශයන් හැර), සහ ඔබේ විචල්‍යයේ කිසිදු ගෝලීය අක්ෂර අඩංගු නොවන බව ඔබට විශ්වාස නම්, ඉහත බොහෝ විට ආරක්ෂිතයි.

නමුත්, ඔබ bash (හෝ ksh, zsh හෝ yash) භාවිතා කරන්නේ නම්, ආරක්ෂිත ක්‍රමයක් තිබේ: අරාවක් භාවිතා කරන්න:

යම් කොන්දේසියක් නම්
එවිට
    නිර්ණායක = (- වර්ගය f) # ඔබට `නිර්ණායක = (" - වර්ගය "" f ")` යැයි පැවසිය හැකිය, නමුත් එය ඇත්තෙන්ම අනවශ්‍යය.
                        # නමුත් එසේ නොකරන්න 'නිර්ණායක = ( "- වර්ගය f") කියන්නේ'.
නැතිනම්
    නිර්ණායක = () # එපා මෙම විධානයෙහි කිසිදු උපුටා දැක්වීම් භාවිතා !
fisome_other_condition 
නම්
එවිට
    නිර්ණායක + = (- mtime +42) # සටහන: අරාවකට එකතු කිරීම (එකතු කිරීම) සඳහා `=` නොව ` + =`.
fi
"$ start_directory" "$ {නිර්ණායක [@]}"   වෙනත්_ සොයා _ආර්ග්ස් සොයා ගන්න

බාෂ් සිට (1) ,

අරාවෙහි ඕනෑම අංගයක් භාවිතයෙන් යොමු කළ හැකිය . … එසේ නම් හෝ  , වචනය සියලුම සාමාජිකයින්ට පුළුල් වේ . මෙම දායකත්වයන් වෙනස් වන්නේ වචනය ද්විත්ව උපුටා දැක්වීම් තුළ දිස් වූ විට පමණි. වචනය ද්වි-උපුටා දැක්වීමක් නම්,… සෑම අංගයක්ම වෙනම වචනයකට විහිදේ.${name[subscript]}subscript@*name${name[@]}name

එබැවින් "${criteria[@]}"(ඉහත උදාහරණයේ දී) criteriaඅරාවෙහි මූලද්‍රව්‍ය ශුන්‍ය, දෙක හෝ හතර දක්වා විහිදේ. විශේෂයෙන්, කොන්දේසි  දෙකම සත්‍ය නොවේ නම්, criteriaඅරාවෙහි අන්තර්ගතයක් නොමැත ( criteria=()ප්‍රකාශය අනුව), කිසිවක්"${criteria[@]}" තක්සේරු නොකරයි (අපහසු හිස් නූලක් පවා නැත).


ඔබ බහුවිධ වචන සමඟ ගනුදෙනු කරන විට මෙය විශේෂයෙන් සිත්ගන්නාසුළු හා සංකීර්ණ වේ, ඒවායින් සමහරක් ඔබ කල්තියා නොදන්නා ගතික (පරිශීලක) ආදානය වන අතර අවකාශය (ය) හෝ වෙනත් විශේෂ අක්ෂර (ය) අඩංගු විය හැකිය. සලකා බලන්න:

printf "සෙවීම සඳහා ගොනු නාමය ඇතුළත් කරන්න:"
fname කියවන්න
if ["$ fname"! = ""]
එවිට
    නිර්ණායක + = (- නම "$ fname")
fi

එය භාවිතා කරන සෑම අවස්ථාවකම $fnameඋපුටා දක්වන ලද සටහන . මෙම පරිශීලක වැනි යමක් ඇතුල් වුවද වැඩ හෝ ,  ඇගයීමට හෝ . (අරාවේ සෑම අංගයක්ම උපුටා දක්වා ඇති බව මතක තබා ගන්න.)foo barfoo*"${criteria[@]}"-name "foo bar"-name "foo*"

සියලුම පොසික්ස් කවච වල අරා ක්‍රියා නොකරයි; අරා යනු ksh / bash / zsh / yash-ism වේ. හැර… සියලුම ෂෙල් වෙඩි සඳහා සහාය වන එක් අරාවක් තිබේ: තර්ක ලැයිස්තුව, හෝ "$@". ඔබ විසින් ආයාචනා කරන ලද තර්ක ලැයිස්තුවෙන් ඔබ සිදු කර ඇත්නම් (උදා: ඔබ සියලු “ස්ථානීය පරාමිතීන්” (තර්ක) විචල්‍යයන් ලෙස පිටපත් කර තිබේ නම් හෝ වෙනත් ආකාරයකින් ඒවා සකසා තිබේ නම්), ඔබට ආර්ග් ලැයිස්තුව අරාවක් ලෙස භාවිතා කළ හැකිය:

යම් කොන්දේසියක් නම්
එවිට
    set - -type f # ඔබට `set -" -type "" f "` යැයි පැවසිය හැකිය, නමුත් එය ඇත්තෙන්ම අනවශ්‍යය.
නැතිනම්
    set -
fisome_other_condition 
නම්
එවිට
    set - "$ @" -mtime +42
fi
# ඒ හා සමානව: සකසන්න - "$ @"-නම "$ fname"
"$ start_directory" "$ @"   වෙනත්_ සොයා _ආර්ග්ස් සොයා ගන්න

මෙම "$@"(ඓතිහාසිකව, පළමු පැමිණි,) ඉදිකිරීමක් ලෙස එම semantics ඇත එය ඔබ ටයිප් නම් ලෙස, වෙනම වචනය සඳහා එක් එක් තර්කය (එනම්, එම තර්කය ලැයිස්තුව එක් එක් මූලද්රව්යය) පුළුල් - ."${name[@]}""$1" "$2" "$3" …

2.5.2 විශේෂ පරාමිතීන් යටතේ පොසික්ස් ෂෙල් විධාන භාෂා පිරිවිතරයෙන් උපුටා ගැනීමකි .

@

    ස්ථානීය පරාමිතීන් දක්වා විහිදේ, එකකින් පටන් ගෙන, මුලින් සකසා ඇති එක් එක් ස්ථානීය පරාමිතීන් සඳහා එක් ක්ෂේත්‍රයක් නිෂ්පාදනය කරයි. …, ආරම්භක ක්ෂේත්‍ර වෙනම ක්ෂේත්‍ර ලෙස රඳවා ගත යුතුය. ස්ථානීය පරාමිතීන් නොමැති නම්, පුළුල් කිරීම ද්විත්ව-මිල ගණන් තුළ @වුවද ශුන්‍ය ක්ෂේත්‍ර ජනනය කරයි @; …

සම්පූර්ණ පා text ය තරමක් ගුප්ත ය; වැදගත්ම කරුණ නම් "$@"ස්ථානීය පරාමිතීන් නොමැති විට ශුන්‍ය ක්ෂේත්‍ර ජනනය වන බව එය නියම කිරීමයි . Note තිහාසික සටහන: "$@"1979 දී බෝර්න් කවචයේ (බාෂ් සඳහා පූර්වගාමියා) ප්‍රථම වරට හඳුන්වා දුන් විට , එහි දෝෂයක් ඇති අතර "$@"එය ස්ථානීය පරාමිතීන් නොමැති විට තනි හිස් නූලකින් ප්‍රතිස්ථාපනය විය; බලන්න ෂෙල් පිටපතක තේරුම කුමක්ද ${1+"$@"}, එය වෙනස් වන්නේ "$@"කෙසේද? සාම්ප්‍රදායික බෝර්න් ෂෙල් පවුලඑයින් ${1+"$@"}අදහස් කරන්නේ කුමක්ද ... එය අවශ්‍ය වන්නේ කොහේද? , සහ "$@"එදිරිව${1+"$@"} .


පළමු තත්වයටද අරා උදව් කරයි:

යම් කොන්දේසියක් නම්
එවිට
    නොසලකා හැරීම = (- i) # ඔබට `නොසලකා හැරීම = (" - i ")` යැයි පැවසිය හැකිය, නමුත් එය ඇත්තෙන්ම අනවශ්‍යය.
නැතිනම්
    නොසලකා හැරීම = () # මෙම විධානයෙහි කිසිදු උපුටා දැක්වීම් භාවිතා නොකරන්න !
fi
grep "$ {නොසලකා හරින්න [@]}"   වෙනත්_ grep _args

____________________

PS (csh)

මෙය නොකියා යා යුතුය, නමුත්, මෙහි නවකයන්ගේ ප්‍රයෝජනය සඳහා: csh, tcsh, ආදිය බෝර්න් / පොසික්ස් ෂෙල් වෙඩි නොවේ. ඔවුන් සම්පූර්ණයෙන්ම වෙනස් පවුලක්. වෙනස් පාට අශ්වයෙක්. සමස්ත බෝල ක්‍රීඩාවක්. බළලුන්ගේ වෙනස් වර්ගයක්. තවත් පිහාටුවක කුරුල්ලන්. තවද, විශේෂයෙන්, වෙනස් පණුවන් කෑන්.

මෙම පිටුවේ පවසා ඇති සමහර දේ csh සඳහා අදාළ වේ; වැනි: ඔබට හොඳ හේතුවක් නොමැති නම් ඔබේ සියලු විචල්‍යයන් උපුටා දැක්වීම හොඳ අදහසකි, තවද ඔබ කරන්නේ කුමක්දැයි ඔබ දන්නා බව ඔබට විශ්වාසයි. නමුත්, csh හි සෑම විචල්‍යයක්ම අරාවකි - සෑම විචල්‍යයක්ම පාහේ එක් මූලද්‍රව්‍යයක අරාවක් වන අතර එය බෝර්න් / පොසික්ස් කවච වල සාමාන්‍ය ෂෙල් විචල්‍යයට සමාන ලෙස ක්‍රියා කරයි. වාක්‍ය ඛණ්ඩය බෙහෙවින් වෙනස් ය (මම අදහස් කරන්නේ භයානක ලෙස ය ). එබැවින් අපි මෙහි csh- පවුලේ ෂෙල් වෙඩි ගැන වැඩි යමක් නොකියමු.


1
එම සටහන csh, ඔබ වඩා භාවිතා කැමතියි $var:qවඩා "$var"අග නව පේළියකට යොමු කිරීමේ අක්ෂරය අක්ෂර අඩංගු (හෝ ඔබ තනි තනිව අරාව මූලද්රව්ය උපුටා දැක්වීමට වඩා, තනි තර්කය බවට ඒවා හිස් අවකාශයක් එක්වන අවශ්ය නම්) විචල්ය සඳහා වැඩ නො කරන බැවින්.
ස්ටෙෆාන් චසෙලාස්

Bash හි, bitrate="--bitrate 320"සමඟ ක්‍රියා කරයි ${bitrate:+$bitrate}, සහ එය විධානය කඩ කරන නිසා ක්‍රියා bitrate=--bitrate 128නොකරනු ඇත ${bitrate:+"$bitrate"}. භාවිතා කිරීමට ආරක්ෂිත ${variable:+$variable}නොමැති "?
ෆ්‍රීඩෝ

@ ෆ්‍රීඩෝ: ඔබේ අදහස අපැහැදිලි ය. මම දැනටමත් පවසා නැති බව ඔබට දැන ගැනීමට අවශ්‍ය කුමක්දැයි මට විශේෂයෙන් පැහැදිලි නැත. දෙවන “නමුත් කුමක් නම්” ශීර්ෂය බලන්න - “නමුත් මට අවශ්‍ය විචල්‍යයක් වචන වලට බෙදිය යුතු නම් කුමක් කළ යුතුද?” එය ඔබගේ තත්වය වන අතර, ඔබ එහි උපදෙස් අනුගමනය කළ යුතුය. නමුත් ඔබට නොහැකි නම් (උදා: ඔබ බාෂ්, ksh, zsh හෝ යෂ් හැර වෙනත් කවචයක් භාවිතා කරන නිසා සහ ඔබ $@වෙනත් දෙයක් සඳහා භාවිතා  කරන නිසා), හෝ ඔබ වෙනත් හේතු නිසා අරාව භාවිතා කිරීම ප්‍රතික්ෂේප කළහොත්, මම යොමු කරමි ඔබ “අනෙක් පිළිතුරෙහි සාකච්ඡා කළ පරිදි”. … (ඉදිරියට)
ජී-මෑන් පවසන්නේ “නැවත

(Cont'd) ... ඔබේ යෝජනාව (භාවිතා ${variable:+$variable}නොමැති "IFS අඩංගු නම්) අසාර්ථක වනු ඇත  -,  0, 2, 3, a, b, e, i, rහෝ  t.
ජී-මෑන් පවසන්නේ 'මොනිකා නැවත

හොඳයි, මගේ විචල්‍යයට අක්ෂර, ඊ, බී, අයි 2 සහ 3 යන දෙකම ඇති අතර තවමත් හොඳින් ක්‍රියා කරයි${bitrate:+$bitrate}
ෆ්‍රීඩෝ

11

ස්ටෙෆේන්ගේ පිළිතුර ගැන මට සැකයක් පැවතුනි, කෙසේ වෙතත් අපයෝජනය කළ හැකිය $#:

$ set `seq 101`

$ IFS=0

$ echo $#
1 1

හෝ $?:

$ IFS=0

$ awk 'BEGIN {exit 101}'

$ echo $?
1 1

මේවා ව්‍යාජ උදාහරණ වේ, නමුත් විභවය පවතී.

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.