Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
syntax:ccmd:case [2012/05/17 12:18]
ormaaj Misc cleanup. Add example.
syntax:ccmd:case [2017/02/08 15:04] (current)
fgrose [Description] describe the separation of PATTERNn from surroundings
Line 13: Line 13:
  
 ===== Description ===== ===== Description =====
-The ''​case''​-statement can execute commands based on a [[syntax:​pattern | pattern matching]] decision. The word ''<​WORD>''​ is matched against every pattern ''<​PATTERNn>''​ and on a match, the associated [[syntax:​basicgrammar#​lists | list]] ''<​LISTn>''​ is executed. Every commandlist is terminated by ''<​nowiki>;;</​nowiki>''​, this rule is optional for the very last commandlist (i.e. you can omit the ''<​nowiki>;;</​nowiki>''​ before the ''​esac''​).+The ''​case''​-statement can execute commands based on a [[syntax:​pattern | pattern matching]] decision. The word ''<​WORD>''​ is matched against every pattern ''<​PATTERNn>''​ and on a match, the associated [[syntax:​basicgrammar#​lists | list]] ''<​LISTn>''​ is executed. Every commandlist is terminated by ''<​nowiki>;;</​nowiki>''​. This rule is optional for the very last commandlist (i.e.you can omit the ''<​nowiki>;;</​nowiki>''​ before the ''​esac''​). Every ''<​PATTERNn>''​ is separated from it's associated ''<​LISTn>''​ by a ''​)'',​ and is optionally preceded by a ''​(''​.
  
-:V4: Bash 4 introduces two new action terminators. The classic behavior using '';;''​ is to execute only the list associated with the first matching pattern, then break out of the ''​case''​ block. The '';&''​ terminator causes ''​case''​ to also execute the next block without testing its pattern. The '';;&''​ operator is like '';;'',​ except the case statement doesn'​t terminate after executing the associated list - Bash just continues testing the next pattern as though the previous pattern didn't match. Using these terminators,​ a ''​case''​ statement can be configured to test against all patterns, or to share code between blocks, for example.+Bash 4 introduces two new action terminators. The classic behavior using '';;''​ is to execute only the list associated with the first matching pattern, then break out of the ''​case''​ block. The '';&''​ terminator causes ''​case''​ to also execute the next block without testing its pattern. The '';;&''​ operator is like '';;'',​ except the case statement doesn'​t terminate after executing the associated list - Bash just continues testing the next pattern as though the previous pattern didn't match. Using these terminators,​ a ''​case''​ statement can be configured to test against all patterns, or to share code between blocks, for example.
  
 The word ''<​WORD>''​ is expanded using //tilde//, //​parameter//​ and //variable expansion//;​ //​arithmetic//,​ //command// and //process substitution//;​ and //quote removal//. **No word splitting, brace, or pathname expansion is done**, which means you can leave expansions unquoted without problems: The word ''<​WORD>''​ is expanded using //tilde//, //​parameter//​ and //variable expansion//;​ //​arithmetic//,​ //command// and //process substitution//;​ and //quote removal//. **No word splitting, brace, or pathname expansion is done**, which means you can leave expansions unquoted without problems:
Line 27: Line 27:
 This is similar to the behavior of the [[syntax:​ccmd:​conditional_expression | conditional expression command ("new test command"​)]] (also no word splitting for expansions). This is similar to the behavior of the [[syntax:​ccmd:​conditional_expression | conditional expression command ("new test command"​)]] (also no word splitting for expansions).
  
-Unlike the C-case-statement,​ only the matching list and nothing else is executed. If more patterns match the word, only the first match is taken. (**Note** the comment about :V4: Bash v4 changes above.)+Unlike the C-case-statement,​ only the matching list and nothing else is executed. If more patterns match the word, only the first match is taken. (**Note** the comment about Bash v4 changes above.)
  
 Multiple ''​|''​-delimited patterns can be specified for a single block. This is a POSIX-compatable equivalent to the ''​@(pattern-list)''​ extglob construct. Multiple ''​|''​-delimited patterns can be specified for a single block. This is a POSIX-compatable equivalent to the ''​@(pattern-list)''​ extglob construct.
Line 36: Line 36:
 Another one of my stupid examples... Another one of my stupid examples...
 <​code>​ <​code>​
-read -rp "Which fruit do you like most? " ​fruit+printf '%s ' 'Which fruit do you like most?
 +read -${BASH_VERSION+e}r ​fruit
  
-case "$fruit" ​in +case $fruit in 
-  apple) ​             echo "Mmmmh... I like those!" +    apple) 
-                      ;; +        ​echo 'Mmmmh... I like those!' 
-  banana) ​            ​echo "Hm, a bit awry, no?" +        ;; 
-                      ;; +    banana) 
-  orange|tangerine) ​  ​echo "Eeeks! I don't like those!+        ​echo 'Hm, a bit awry, no?' 
-                      echo "​Go ​away!" +        ;; 
-                      exit 1 +    orange|tangerine) 
-                      ;; +        ​echo $'Eeeks! I don\'t like those!\nGo away!' 
-  *)                  echo "​Unknown fruit - sure it isn't toxic?"​ +        exit 1 
-                      ;;+        ;; 
 +    *) 
 +        ​echo "​Unknown fruit - sure it isn't toxic?"​
 esac esac
 +</​code>​
 +
 +Here's a practical example showing a common pattern involving a ''​case''​ statement. If the first argument is one of a valid set of alternatives,​ then perform some sysfs operations under Linux to control a video card's power profile. Otherwise, show a usage synopsis, and print the current power profile and GPU temperature.
 +<code bash>
 +# Set radeon power management
 +function clk {
 + typeset base=/​sys/​class/​drm/​card0/​device
 + [[ -r ${base}/​hwmon/​hwmon0/​temp1_input && -r ${base}/​power_profile ]] || return 1
 +
 + case $1 in
 + low|high|default)
 + printf '​%s\n'​ "temp: $(<​${base}/​hwmon/​hwmon0/​temp1_input)C"​ "old profile: $(<​${base}/​power_profile)"​
 + echo "​$1"​ >​${base}/​power_profile
 + echo "new profile: $(<​${base}/​power_profile)"​
 + ;;
 + *)
 + echo "​Usage:​ $FUNCNAME [ low | high | default ]"
 + printf '​%s\n'​ "temp: $(<​${base}/​hwmon/​hwmon0/​temp1_input)C"​ "​current profile: $(<​${base}/​power_profile)"​
 + esac
 +}
 </​code>​ </​code>​
  
 A template for experiments with ''​case''​ logic, showing shared code between blocks using '';&'',​ and the non-short-circuiting '';;&''​ operator: A template for experiments with ''​case''​ logic, showing shared code between blocks using '';&'',​ and the non-short-circuiting '';;&''​ operator:
-<​code>​+<​code ​bash>
 #​!/​usr/​bin/​env bash #​!/​usr/​bin/​env bash
  
Line 89: Line 112:
 ===== Portability considerations ===== ===== Portability considerations =====
  
-  * Only the '';;''​ delimiter is specified by POSIX+  * Only the '';;''​ delimiter is specified by POSIX.
   * zsh and mksh use the '';​|''​ control operator instead of Bash's '';;&''​. Mksh has '';;&''​ for Bash compatability (undocumented).   * zsh and mksh use the '';​|''​ control operator instead of Bash's '';;&''​. Mksh has '';;&''​ for Bash compatability (undocumented).
-  * ksh93 has the '';&''​ operator, but not '';;&''​. +  * ksh93 has the '';&''​ operator, but no '';;&'' ​or equivalent
 +  * ksh93, mksh, zsh, and posh support a historical syntax where open and close braces may be used in place of ''​in''​ and ''​esac'':​ ''​case word { x) ...; };''​. This is similar to the alternate form Bash supports for its [[syntax/​ccmd/​classic_for | for loops]], but Bash doesn'​t support this syntax for ''​case..esac''​.
 ===== See also ===== ===== See also =====
-  * [[POSIX case conditional construct|http://​pubs.opengroup.org/​onlinepubs/​9699919799/​utilities/​V3_chap02.html#​tag_18_09_04_05]]+  * [[http://​pubs.opengroup.org/​onlinepubs/​9699919799/​utilities/​V3_chap02.html#​tag_18_09_04_05|POSIX case conditional construct]]
  
  • syntax/ccmd/case.1337257115.txt
  • Last modified: 2012/05/17 12:18
  • by ormaaj