විචල්යයක් හිස් හෝ අවකාශයන් පමණක් තිබේදැයි පරීක්ෂා කරන්නේ කෙසේද?


263

paramහිස් නොවේ නම් පහත දැක්වෙන bash syntax සත්‍යාපනය කරයි :

 [[ !  -z  $param  ]]

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

param=""
[[ !  -z  $param  ]] && echo "I am not zero"

නිමැවුමක් සහ එහි දඩය නැත.

නමුත් paramඅවකාශ අක්ෂර එකක් (හෝ වැඩි ගණනක්) හැර හිස් වූ විට නඩුව වෙනස් වේ:

param=" " # one space
[[ !  -z  $param  ]] && echo "I am not zero"

"මම ශුන්‍ය නොවේ" යනු ප්‍රතිදානයයි.

අභ්‍යවකාශ අක්ෂර පමණක් අඩංගු විචල්‍යයන් හිස් යැයි සැලකීමට පරීක්ෂණය වෙනස් කරන්නේ කෙසේද?


5
සිට man test: -z STRING - the length of STRING is zero. ඔබට ඇති සියලුම අවකාශයන් ඉවත් කිරීමට අවශ්‍ය නම් $param, භාවිතා කරන්න${param// /}
dchirikov

7
වාව්trim() කිසිසේත්ම * නික්ස් සඳහා සාදන ලද සරල ශ්‍රිතයක් නැද්ද? එතරම් සරල දෙයක් සාක්ෂාත් කර ගැනීම සඳහා විවිධාකාර
හක්ක

6
@ADTC $ (sed 's / ^ + s + | \ s + $ // g' <<< $ string) මට ප්‍රමාණවත් තරම් සරල බව පෙනේ. රෝදය ප්‍රතිනිර්මාණය කරන්නේ ඇයි?
jbowman

4
එය දිලිසෙන නිසා
ඉන්වර්සස්

1
එය සඳහන් [[ ! -z $param ]]කිරීම සමාන වේ test ! -z $param.
නෝවා සුස්මාන්

Answers:


313

පළමුව, -zපරීක්ෂණය පැහැදිලිවම සඳහා බව සලකන්න :

නූල් වල දිග ශුන්‍ය වේ

එනම්, ශුන්‍ය නොවන දිගක් ඇති බැවින් අවකාශයන් පමණක් අඩංගු නූලක් යටතේ සත්‍ය නොවිය යුතුය -z.

ඔබට අවශ්‍ය වන්නේ රටා ප්‍රතිස්ථාපන පරාමිති ප්‍රසාරණය භාවිතා කරමින් විචල්‍යයෙන් අවකාශය ඉවත් කිරීමයි :

[[ -z "${param// }" ]]

මෙය paramවිචල්‍යය පුළුල් කරන අතර රටාවේ සියලුම ගැලපීම් (තනි ඉඩක්) කිසිවක් නොමැතිව ප්‍රතිස්ථාපනය කරයි , එබැවින් එහි අවකාශයන් පමණක් ඇති නූලක් හිස් නූලක් දක්වා පුළුල් වේ.


එය ක්‍රියාත්මක වන ආකාරය පිළිබඳ විකාර සහගත දෙය නම් ${var/pattern/string}පළමු දිගම තරගය patternසමඟ ප්‍රතිස්ථාපනය කිරීමයි string. (ඉහත පරිදි) patternසමඟ ආරම්භ වන විට /එය සියලු තරඟ ප්‍රතිස්ථාපනය කරයි . ප්‍රතිස්ථාපනය හිස් බැවින් අපට අවසාන /හා stringවටිනාකම අතහැර දැමිය හැකිය :

$ {පරාමිතිය / රටාව / නූල්}

මෙම රටාව පමණක් ගොනු පුළුල් ලෙස රටාව ඉදිරිපත් කිරීමට පුළුල් කර ඇත. පරාමිතිය පුළුල් වන අතර එහි වටිනාකමට සාපේක්ෂව රටාවේ දිගම ගැලපීම නූල් මගින් ප්‍රතිස්ථාපනය වේ . නම් රටාව '/' ආරම්භ වීමත් සමග, සියලු තරග රටාව වෙනුවට ඇත string . සාමාන්යයෙන් ප්රථම තරගය පමණක් ප්රතිස්ථාපනය වේ. ... නූල් ශුන්‍ය නම්, රටාවේ ගැලපීම් මකා දමා / පහත රටාව මඟ හැරිය හැක.

සියල්ලට පසු, අපි ${param// }සියලු අවකාශයන් මකා දැමීමට අවසන් කරමු .

සටහන වර්තමාන නමුත් ඒ ksh(එය මුලින්ම එහිදී), zshසහ bashකාරක රීති POSIX නොවන අතර භාවිතා කළ නොකළ යුතු බව, shපිටපත්.


1
පාවිච්චි කළේ sedඔවුන් කිව්වා ... ඔවුන් කියපු echoවිචල්‍යය විතරයි ...
මයික්ස්ටර්

4
හ්ම්. එය එසේ ${var/pattern/string}නම් [[ -z ${param/ /} ]], කප්පාදුව අතර ඇති අවකාශය රටාව විය යුතු අතර නූල් වීමට පසු කිසිවක් නැත.
ජෙසී චිෂොල්ම්

Es ජෙසිෂිෂොල්ම් "ප්‍රතිස්ථාපනය හිස් බැවින් අපට අවසාන / සහ නූල් අගය මඟ හැරිය හැක"; " නූල් අහෝසි නම්, රටාවේ ගැලපීම් මකා දමන අතර / පහත රටාව මඟ හැරිය හැක."
මයිකල් හෝමර්

6
Ic මයිකල්හෝමර් පිළිතුර [[ -z "${param// }" ]]නිසැකවම patternහිස් බව පෙනේ, replacement stringඑය තනි අවකාශයකි. අහ්! මට දැන් එය පෙනේ if pattern begins with a slash. එබැවින් රටාව පවතින / අතර නූල අතහැර දමා හිස්ව පවතී. ස්තූතියි.
ජෙසී චිෂොල්ම්

bash note: set -o nounset (set -u) හි ධාවනය වන අතර, පරාමිතිය සකසා නොමැති නම් (ශුන්‍ය හෝ අවකාශයෙන් පිරී ඇතිවාට වඩා), එවිට මෙය අසීමිත විචල්‍ය දෝෂයක් ජනනය කරනු ඇත. (set + u; .....) මෙම පරීක්ෂණයෙන් නිදහස් වේ.
බ්‍රයන් ක්‍රිස්මන්

32

බලයලත් කට්ටලයක අක්ෂර පමණක් අඩංගු වන්නේ දැයි පරීක්ෂා කිරීමට පහසුම ක්‍රමය නම් අනවසර අක්ෂර තිබේද යන්න පරීක්ෂා කිරීමයි. මේ අනුව, නූලෙහි ඇත්තේ අවකාශයන් පමණක් දැයි පරීක්ෂා කරනවා වෙනුවට, නූලට අවකාශය හැර වෙනත් අක්ෂරයක් තිබේදැයි පරීක්ෂා කරන්න. Bash, ksh හෝ zsh වලින්:

if [[ $param = *[!\ ]* ]]; then
  echo "\$param contains characters other than space"
else
  echo "\$param consists of spaces only"
fi

“අවකාශයන්ගෙන් පමණක් සමන්විත” යන්නට හිස් (හෝ සැකසූ) විචල්‍යයක් ඇතුළත් වේ.

ඔබට ඕනෑම හිස් අවකාශයක් සඳහා පරීක්ෂා කිරීමට අවශ්‍ය විය හැකිය. [[ $param = *[^[:space:]]* ]]ස්ථාන සැකසීම් භාවිතා කිරීමට භාවිතා කරන්න , හෝ ඔබට පරීක්ෂා කිරීමට අවශ්‍ය සුදු පැහැති අක්ෂර ලැයිස්තුවක්, උදා: [[ $param = *[$' \t\n']* ]]අවකාශය, ටැබ් හෝ නව රේඛාව පරීක්ෂා කිරීම.

=ඇතුළත රටාවකට එරෙහිව නූලක් ගැලපීම [[ … ]]ksh දිගුවකි (bash සහ zsh වලද පවතී). ඕනෑම බෝර්න් / පොසික්ස් විලාසිතාවක, රටාවකට caseඑරෙහිව නූලක් ගැලපීමට ඔබට ඉදිකිරීම් භාවිතා කළ හැකිය . බොහෝ සාමාන්‍ය ප්‍රකාශන වාක්‍ය ඛණ්ඩවලට !වඩා අක්ෂර කට්ටලයක් ප්‍රතික්ෂේප කිරීමට සම්මත ෂෙල් රටා භාවිතා කරන බව සලකන්න ^.

case "$param" in
  *[!\ ]*) echo "\$param contains characters other than space";;
  *) echo "\$param consists of spaces only";;
esac

හිස් අවකාශයේ අක්ෂර පරීක්ෂා කිරීම සඳහා, $'…'වාක්‍ය ඛණ්ඩය ksh / bash / zsh සඳහා විශේෂිත වේ; ඔබට මෙම අක්ෂර ඔබේ ස්ක්‍රිප්ටයට වචනාර්ථයෙන් ඇතුළත් කළ හැකිය (බැක්ස්ලෑෂ් + නිව්ලයින් කිසිවක් නැති වන පරිදි නව රේඛාවක් උපුටා දැක්වීම් තුළ තිබිය යුතු බව සලකන්න), හෝ ඒවා ජනනය කරන්න, උදා.

whitespace=$(printf '\n\t ')
case "$param" in
  *[!$whitespace]*) echo "\$param contains non-whitespace characters";;
  *) echo "\$param consists of whitespace only";;
esac

මෙය බොහෝ දුරට විශිෂ්ටයි - නමුත්, තවමත්, එය ඇසූ පරිදි ප්‍රශ්නයට පිළිතුරු සපයන්නේ නැත. දැනට එය සැකසූ හෝ හිස් කවච විචල්‍යයක් සහ අවකාශයන් පමණක් අඩංගු එකක් අතර වෙනස ඔබට පැවසිය හැකිය . ඔබ මගේ යෝජනාව පිළිගන්නේ නම්, සැකසීම් සඳහා ෂෙල් විචල්‍යයක් පැහැදිලිව පරීක්‍ෂා කරන වෙනත් පිළිතුරකින් ඔබ තවමත් සම්ප්‍රේෂණය නොකළ පරාමි විස්තාරණ පෝරමය එක් කරනු ඇත - මම අදහස් කළේ ${var?not set}- එම පරීක්ෂණය සමත් වී දිවි ගලවා ගැනීම ඔබේ ගැලපෙන විචල්‍යයක් *) caseනියත ලෙස බලපාන බව සහතික කරයි. උදාහරණයක් ලෙස පිළිතුර.
mikeserv

නිවැරදි - මෙම, ඇත්ත වශයෙන්ම, හැකි ද යන ප්රශ්නය පිළිතුරු මුලින් ඉල්ලා, නමුත් එය බැවින් එය මූලිකව ප්රශ්නය අර්ථය වෙනස් නිසා ඔබගේ පිළිතුර විරෝධියි ආකාරයකින් සංස්කරණය කර ඇත.
mikeserv

ඔබට අවශ්ය [[ $param = *[!\ ]* ]]තුළ mksh.
ස්ටෙෆාන් චසෙලාස්

22

POSIXly:

case $var in
  (*[![:blank:]]*) echo '$var contains non blank';;
  (*) echo '$var contains only blanks or is empty or unset'
esac

අතර වෙනස හිස් , නොවන හිස් , හිස් , ශූන්යය :

case ${var+x$var} in
  (x) echo empty;;
  ("") echo unset;;
  (x*[![:blank:]]*) echo non-blank;;
  (*) echo blank
esac

[:blank:]තිරස් පරතර අක්ෂර සඳහා වේ (ASCII හි අවකාශය සහ පටිත්ත, නමුත් බොහෝ විට ඔබේ පෙදෙසෙහි තවත් කිහිපයක් තිබේ; සමහර පද්ධතිවල නොබිඳිය හැකි අවකාශය (ලබා ගත හැකි ස්ථාන) ඇතුළත් වේ, සමහර ඒවා එසේ නොවේ). ඔබට සිරස් පරතර අක්‍ෂර අවශ්‍ය නම් (නව රේඛාව හෝ පෝරම පෝෂණය වැනි), ආදේශ [:blank:]කරන්න [:space:].


POSIXly වඩාත් සුදුසු වන්නේ එය (වඩා හොඳ) ඉරක් සමඟ ක්‍රියා කරන බැවිනි.
කෙන් ෂාප්

zshගැටලුවක් ඇති බව පෙනේ [![:blank:]], එය මතු :bකිරීම අවලංගු විකරණකාරකයකි. දී shහා kshසංස්කෘතික උරුමයන් විනාශ කර දැමීම, එය සිදුවීම මතු සඳහා සොයාගත නොහැකි[
cuonglm

@cuonglm, ඔබ උත්සාහ කළේ කුමක්ද? var=foo zsh -c 'case ${var+x$var} in (x*[![:blank:]]*) echo x; esac'මට හොඳයි. සොයාගත නොහැකි වූ සිදුවීම අන්තර්ක්‍රියාකාරී ෂෙල් වෙඩි සඳහා පමණි.
ස්ටෙෆාන් චසෙලාස්

@ ස්ටෙෆාන් චැසෙලාස්: ආහ්, මම අන්තර්ක්‍රියාකාරී ෂෙල් වෙඩි සමඟ උත්සාහ කළා. මෙම :bවැරදි විකරණකාරකය ටිකක් අමුතුයි.
cuonglm

1
@FranklinYu, මෙහෙයුම් පද්ධතිය මත / X shඇත bashඉදි --enable-xpg-echo-defaultහා --enable-strict-posix-default(බහු යුනික්ස් අනුකූල විය කිරීමට එසේ echo '\t'ටැබ් outputting).
ස්ටෙෆාන් චසෙලාස්

5

හොඳ ස්ක්‍රිප්ටින් භාෂාවක ස්ක්‍රිප්ට් එකක් වෙනුවට ෂෙල් ස්ක්‍රිප්ට් එකක් ලිවීමට ඉතිරිව ඇති එකම හේතුව වන්නේ ආන්තික අතේ ගෙන යා හැකි හැකියාව ඉක්මවා යන කාරණයක් නම්. /bin/shඔබට ඇති බවට ඔබට සහතික විය හැකි එකම දෙය උරුමයයි , නමුත් උදාහරණයක් ලෙස පර්ල්, බාෂ්ට වඩා හරස් වේදිකාවක් ලබා ගත හැකිය. එමනිසා, කිසි විටෙකත් විශ්වීය නොවන අංග භාවිතා කරන ෂෙල් ස්ක්‍රිප්ට් ලියන්න එපා - සහ POSIX.1-2001 ට පෙර හිමිකාර යුනික්ස් වෙළෙන්දෝ කිහිප දෙනෙක් ඔවුන්ගේ ෂෙල් පරිසරය ශීත කළ බව මතක තබා ගන්න .

මෙම පරීක්ෂණය සිදු කිරීම සඳහා අතේ ගෙන යා හැකි ක්‍රමයක් ඇත, නමුත් ඔබ භාවිතා කළ යුත්තේ tr:

[ "x`printf '%s' "$var" | tr -d "$IFS"`" = x ]

(පහසුකමෙහි පෙරනිමි අගය $IFSඅවකාශය, පටිත්ත සහ නව රේඛාවකි.)

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


1
ඒක ටිකක් කැටි වෙලා. නූලක යම් අක්ෂර අඩංගු දැයි පරීක්ෂා කිරීමට සුපුරුදු අතේ ගෙන යා හැකි ක්‍රමය සමඟcase ඇත.
ගිලෙස්ගේ SO- නපුරු වීම නවත්වන්න '

@Gilles මම හිතන්නේ නැහැ එය ලිවීමට හැකි එකක් කියලා caseඑක්කෝ හිස් කිරීම, හෝ අඩංගු වන වැලක් සොයා ගැනීමට glob පමණක් whitespace අක්ෂර. (එය regexp සමග පහසු වනු ඇත, නමුත් caseඔබ හිස් පේලි ගැන සැලකිලිමත් නම් regexps කරන්නේ නැත ඔබගේ පිළිතුර දී ඉදිකිරීමක් වැඩ නැහැ..)
zwol

1
මගේ පිළිතුරේ උදාහරණයක් ලෙස මම අවකාශයන් ලබා දුන්නෙමි. හිස් අවකාශයේ අක්ෂර පරීක්ෂා කිරීම සමානව පහසු ය : case $param in *[![:space:]]*) …. ඔබට IFSඅක්ෂර සඳහා පරීක්ෂා කිරීමට අවශ්‍ය නම් , ඔබට රටාව භාවිතා කළ හැකිය *[$IFS]*.
ගිලෙස්ගේ SO- නපුරු වීම නවත්වන්න '

1
ikmikeserv සැබවින්ම බැරෑරුම් ලෙස ආරක්‍ෂිත පිටපතක, ඔබ පැහැදිලිවම <space><tab><newline>ආරම්භයේදීම IFS සකසා ඇති අතර නැවත එය ස්පර්ශ නොකරන්න. මම හිතුවා ඒක අවධානය වෙනතකට යොමු කරයි කියලා.
zwol

1
රටා වල විචල්‍යයන් සම්බන්ධයෙන්, මම සිතන්නේ එය සියලුම බෝර්න් අනුවාදවල සහ සියලුම පොසික්ස් කවච වල ක්‍රියා කරන බවයි; සිද්ධි රටා හඳුනා ගැනීමට සහ විචල්‍ය ප්‍රසාරණය අක්‍රිය කිරීමට එයට අමතර කේතයක් අවශ්‍ය වන අතර එය කිරීමට හේතුවක් ගැන මට සිතිය නොහැක. .profileබොහෝ බෝර්න් ෂෙල් වෙඩි මගින් ක්‍රියාත්මක කර ඇති අවස්ථා කිහිපයක් මා සතුව ඇත. පෙරනිමි නොවන අගයන් (හිස් (හෝ සකසා නැති), අඩංගු , ආරම්භ හෝ ආරම්භ කර ඇත්නම් ) ඇත්ත වශයෙන්ම [$IFS]අදහස් නොකරන දේ නොකරයි . IFS]!^
ගිලෙස්ගේ SO- නපුරු වීම නවත්වන්න '

5
if [[ -n "${variable_name/[ ]*\n/}" ]]
then
    #execute if the the variable is not empty and contains non space characters
else
    #execute if the variable is empty or contains only spaces
fi

මෙය තනි අවකාශයක් පමණක් නොව ඕනෑම සුදු අවකාශයක් ඉවත් කරයි, නේද? ස්තූතියි
ඇලෙක්සැන්ඩර් මිල්ස්

1

විචල්‍යය හිස්ද නැතිනම් අවකාශ තිබේද යන්න පරීක්ෂා කිරීම සඳහා, ඔබට මෙම කේතයද භාවිතා කළ හැකිය:

${name:?variable is empty}

2
"හෝ අවකාශයන් අඩංගු" සත්‍ය නොවන නිසා ඔබේ පිළිතුර පහත් කොට සලකනු ඇතැයි මම සිතමි.
බර්න්හාර්ඩ්

ප්‍රවේශම් වන්න - එය වත්මන් කවචය මරා දමයි. (: $ {උපසෙල්?}) තුළට දැමීම වඩා හොඳය. එසේම - එය stderr වෙත ලියනු ඇත - ඔබට නැවත හරවා යැවීමට අවශ්‍ය වනු ඇත. හා වඩාත් වැදගත් විචල්ය ගේ සැබෑ වටිනාකම ඇගයීමට එය ශූන්යය හෝ ශූන්ය නොවේ නම් ඒ. එහි විධානයක් තිබේ නම්, ඔබ එය ක්‍රියාත්මක කරන්න. එම පරීක්ෂණය ක්‍රියාත්මක කිරීම වඩාත් සුදුසුය :.
mikeserv

එය ෂෙල් එක මරන්නේ කෙසේද? ඔබටත් මෙය පරීක්‍ෂා කළ හැකිය, පළමුව නිර්වචනය කර name=aaaaමෙම විධානය ක්‍රියාත්මක echo ${name:?variable is empty}කිරීමෙන් එය විචල්‍ය නාමයේ අගය මුද්‍රණය කර දැන් මෙම විධානය ක්‍රියාත්මක echo ${name1:?variable is empty}කිරීමෙන් එය මුද්‍රණය වනු ඇත -sh: name1: විචල්‍යය හිස්
pratik

ඔව් - echo ${name:?variable is empty}එක්කෝ $nameශුන්‍ය නොවන අගයක් තක්සේරු කරයි හෝ එය කවචය විනාශ කරයි. ඉතින් එකම හේතුව නිසා ඔබත් prompt > $randomvarනොකළ යුතුයි ${var?}- එහි විධානයක් තිබේ නම්, එය බොහෝ විට ක්‍රියාත්මක වනු ඇත - එය කුමක්දැයි ඔබ නොදනී. අන්තර්ක්‍රියාකාරී කවචයකින් පිටවිය යුතු නැත - ඒ නිසා ඔබේ නොවේ. තවමත්, ඔබට සමහර පරීක්ෂණ දැකීමට අවශ්‍ය නම්, ඒවායින් බොහොමයක් මෙහි තිබේ. . මෙය එතරම් දිගු නොවේ ...
මයික්සර්ව්

1

පරාමිතිය සැකසූ / නිර්වචනය නොකළ හෝ හිස් නම් (බාෂ්, ksh සහ zsh වලින්) ඔබ පළ කළ කේතය [[ ! -z $param ]] && echo "I am not zero"මුද්‍රණය I am not zeroවේ.

කිරීමට param පමණක් අවකාශ (ඉවත් අවකාශයන්), POSIXly (ෂෙල් වෙඩි පුළුල් පරාසයක සඳහා) අඩංගු වේ නම් මුද්රණය:

 [   -z "${param#"${param%%[! ]*}"}"   ] && echo "empty"

පැහැදිලි කිරීම:

  • ${param# … }සඳහා ඉවත් ප්රමුඛ පෙළ.
  • එම ප්‍රමුඛ පෙළ ලබා දෙන්නේ: ${param%%[! ]*}
  • එය ඕනෑම අවකාශයක් නොවන අක්ෂරයකට පෙර සියලු අවකාශයන් දක්වා විහිදේ , එනම් සියලු ප්‍රමුඛ අවකාශයන්.

සමස්ත ප්‍රසාරණයේ අවසාන ප්‍රති result ලය වනුයේ සියලුම ප්‍රමුඛ අවකාශයන් ඉවත් වීමයි.

මෙම පුළුල් කළ ප්‍රති result ලය දිග 0 නම් පරීක්ෂා කරනු ලැබේ.

  • ප්‍රති result ලය හිස් නම්, එක්කෝ විචල්‍යය හිස් විය, නැතහොත්
  • ප්‍රමුඛ අවකාශයන් ඉවත් කිරීමෙන් එය හිස් විය.

එමනිසා, පරීක්ෂණය සත්‍ය නම්, විචල්‍යය දැනටමත් හිස්ව තිබුනි, නැතහොත් එහි ඉඩ ප්‍රමාණයක් තිබුනි.


සංකල්පය තවත් අක්ෂර වර්ග දක්වා විහිදීම පහසුය. ටැබ් ද ඇතුළත් කිරීමට, වරහන් ප්‍රකාශනය තුළ පැහැදිලි පටිත්තක් තබන්න:

 [ -z "${param#"${param%%[!     ]*}"}" ] && echo "empty"

හෝ ඔබට ඉවත් කිරීමට අවශ්‍ය අක්ෂර සමඟ විචල්‍යයක් භාවිතා කරන්න:

 var=$' \t'                                    # in ksh, bash, zsh
 [ -z "${param#"${param%%[!$var]*}"}" ] && echo "empty"

හෝ ඔබට POSIX "අක්‍ෂර පන්ති ප්‍රකාශනය" භාවිතා කළ හැකිය (හිස් යන්නෙන් අවකාශය සහ පටිත්ත):

 [ -z "${param#"${param%%[![:blank:]]*}"}" ] && echo "empty"

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.