diff options
| author | Craig Jennings <c@cjennings.net> | 2024-04-07 13:41:34 -0500 |
|---|---|---|
| committer | Craig Jennings <c@cjennings.net> | 2024-04-07 13:41:34 -0500 |
| commit | 754bbf7a25a8dda49b5d08ef0d0443bbf5af0e36 (patch) | |
| tree | f1190704f78f04a2b0b4c977d20fe96a828377f1 /devdocs/bash/conditional-constructs.html | |
new repository
Diffstat (limited to 'devdocs/bash/conditional-constructs.html')
| -rw-r--r-- | devdocs/bash/conditional-constructs.html | 68 |
1 files changed, 68 insertions, 0 deletions
diff --git a/devdocs/bash/conditional-constructs.html b/devdocs/bash/conditional-constructs.html new file mode 100644 index 00000000..23d3678c --- /dev/null +++ b/devdocs/bash/conditional-constructs.html @@ -0,0 +1,68 @@ +<h1 class="subsubsection">Conditional Constructs</h1> <dl compact> <dt id="index-if"><span><code>if</code></span></dt> <dd> + <p>The syntax of the <code>if</code> command is: </p> <div class="example"> <pre class="example">if test-commands; then + consequent-commands; +[elif more-test-commands; then + more-consequents;] +[else alternate-consequents;] +fi +</pre> +</div> <p>The <var>test-commands</var> list is executed, and if its return status is zero, the <var>consequent-commands</var> list is executed. If <var>test-commands</var> returns a non-zero status, each <code>elif</code> list is executed in turn, and if its exit status is zero, the corresponding <var>more-consequents</var> is executed and the command completes. If ‘<samp>else <var>alternate-consequents</var></samp>’ is present, and the final command in the final <code>if</code> or <code>elif</code> clause has a non-zero exit status, then <var>alternate-consequents</var> is executed. The return status is the exit status of the last command executed, or zero if no condition tested true. </p> </dd> <dt id="index-case"><span><code>case</code></span></dt> <dd> + <p>The syntax of the <code>case</code> command is: </p> <div class="example"> <pre class="example">case word in + [ [(] pattern [| pattern]…) command-list ;;]… +esac +</pre> +</div> <p><code>case</code> will selectively execute the <var>command-list</var> corresponding to the first <var>pattern</var> that matches <var>word</var>. The match is performed according to the rules described below in <a href="pattern-matching">Pattern Matching</a>. If the <code>nocasematch</code> shell option (see the description of <code>shopt</code> in <a href="the-shopt-builtin">The Shopt Builtin</a>) is enabled, the match is performed without regard to the case of alphabetic characters. The ‘<samp>|</samp>’ is used to separate multiple patterns, and the ‘<samp>)</samp>’ operator terminates a pattern list. A list of patterns and an associated command-list is known as a <var>clause</var>. </p> <p>Each clause must be terminated with ‘<samp>;;</samp>’, ‘<samp>;&</samp>’, or ‘<samp>;;&</samp>’. The <var>word</var> undergoes tilde expansion, parameter expansion, command substitution, arithmetic expansion, and quote removal (see <a href="shell-parameter-expansion">Shell Parameter Expansion</a>) before matching is attempted. Each <var>pattern</var> undergoes tilde expansion, parameter expansion, command substitution, arithmetic expansion, process substitution, and quote removal. </p> <p>There may be an arbitrary number of <code>case</code> clauses, each terminated by a ‘<samp>;;</samp>’, ‘<samp>;&</samp>’, or ‘<samp>;;&</samp>’. The first pattern that matches determines the command-list that is executed. It’s a common idiom to use ‘<samp>*</samp>’ as the final pattern to define the default case, since that pattern will always match. </p> <p>Here is an example using <code>case</code> in a script that could be used to describe one interesting feature of an animal: </p> <div class="example"> <pre class="example">echo -n "Enter the name of an animal: " +read ANIMAL +echo -n "The $ANIMAL has " +case $ANIMAL in + horse | dog | cat) echo -n "four";; + man | kangaroo ) echo -n "two";; + *) echo -n "an unknown number of";; +esac +echo " legs." +</pre> +</div> <p>If the ‘<samp>;;</samp>’ operator is used, no subsequent matches are attempted after the first pattern match. Using ‘<samp>;&</samp>’ in place of ‘<samp>;;</samp>’ causes execution to continue with the <var>command-list</var> associated with the next clause, if any. Using ‘<samp>;;&</samp>’ in place of ‘<samp>;;</samp>’ causes the shell to test the patterns in the next clause, if any, and execute any associated <var>command-list</var> on a successful match, continuing the case statement execution as if the pattern list had not matched. </p> <p>The return status is zero if no <var>pattern</var> is matched. Otherwise, the return status is the exit status of the <var>command-list</var> executed. </p> </dd> <dt id="index-select"><span><code>select</code></span></dt> <dd> <p>The <code>select</code> construct allows the easy generation of menus. It has almost the same syntax as the <code>for</code> command: </p> <div class="example"> <pre class="example">select name [in words …]; do commands; done +</pre> +</div> <p>The list of words following <code>in</code> is expanded, generating a list of items, and the set of expanded words is printed on the standard error output stream, each preceded by a number. If the ‘<samp>in <var>words</var></samp>’ is omitted, the positional parameters are printed, as if ‘<samp>in "$@"</samp>’ had been specified. <code>select</code> then displays the <code>PS3</code> prompt and reads a line from the standard input. If the line consists of a number corresponding to one of the displayed words, then the value of <var>name</var> is set to that word. If the line is empty, the words and prompt are displayed again. If <code>EOF</code> is read, the <code>select</code> command completes and returns 1. Any other value read causes <var>name</var> to be set to null. The line read is saved in the variable <code>REPLY</code>. </p> <p>The <var>commands</var> are executed after each selection until a <code>break</code> command is executed, at which point the <code>select</code> command completes. </p> <p>Here is an example that allows the user to pick a filename from the current directory, and displays the name and index of the file selected. </p> <div class="example"> <pre class="example">select fname in *; +do + echo you picked $fname \($REPLY\) + break; +done +</pre> +</div> </dd> <dt><span><code>((…))</code></span></dt> <dd> +<div class="example"> <pre class="example">(( expression )) +</pre> +</div> <p>The arithmetic <var>expression</var> is evaluated according to the rules described below (see <a href="shell-arithmetic">Shell Arithmetic</a>). The <var>expression</var> undergoes the same expansions as if it were within double quotes, but double quote characters in <var>expression</var> are not treated specially are removed. If the value of the expression is non-zero, the return status is 0; otherwise the return status is 1. </p> </dd> <dt id="index-_005b_005b"><span><code>[[…]]</code></span></dt> <dd> + <div class="example"> <pre class="example">[[ expression ]] +</pre> +</div> <p>Return a status of 0 or 1 depending on the evaluation of the conditional expression <var>expression</var>. Expressions are composed of the primaries described below in <a href="bash-conditional-expressions">Bash Conditional Expressions</a>. The words between the <code>[[</code> and <code>]]</code> do not undergo word splitting and filename expansion. The shell performs tilde expansion, parameter and variable expansion, arithmetic expansion, command substitution, process substitution, and quote removal on those words (the expansions that would occur if the words were enclosed in double quotes). Conditional operators such as ‘<samp>-f</samp>’ must be unquoted to be recognized as primaries. </p> <p>When used with <code>[[</code>, the ‘<samp><</samp>’ and ‘<samp>></samp>’ operators sort lexicographically using the current locale. </p> <p>When the ‘<samp>==</samp>’ and ‘<samp>!=</samp>’ operators are used, the string to the right of the operator is considered a pattern and matched according to the rules described below in <a href="pattern-matching">Pattern Matching</a>, as if the <code>extglob</code> shell option were enabled. The ‘<samp>=</samp>’ operator is identical to ‘<samp>==</samp>’. If the <code>nocasematch</code> shell option (see the description of <code>shopt</code> in <a href="the-shopt-builtin">The Shopt Builtin</a>) is enabled, the match is performed without regard to the case of alphabetic characters. The return value is 0 if the string matches (‘<samp>==</samp>’) or does not match (‘<samp>!=</samp>’) the pattern, and 1 otherwise. </p> <p>If you quote any part of the pattern, using any of the shell’s quoting mechanisms, the quoted portion is matched literally. This means every character in the quoted portion matches itself, instead of having any special pattern matching meaning. </p> <p>An additional binary operator, ‘<samp>=~</samp>’, is available, with the same precedence as ‘<samp>==</samp>’ and ‘<samp>!=</samp>’. When you use ‘<samp>=~</samp>’, the string to the right of the operator is considered a <small>POSIX</small> extended regular expression pattern and matched accordingly (using the <small>POSIX</small> <code>regcomp</code> and <code>regexec</code> interfaces usually described in <i>regex</i>(3)). The return value is 0 if the string matches the pattern, and 1 if it does not. If the regular expression is syntactically incorrect, the conditional expression returns 2. If the <code>nocasematch</code> shell option (see the description of <code>shopt</code> in <a href="the-shopt-builtin">The Shopt Builtin</a>) is enabled, the match is performed without regard to the case of alphabetic characters. </p> <p>You can quote any part of the pattern to force the quoted portion to be matched literally instead of as a regular expression (see above). If the pattern is stored in a shell variable, quoting the variable expansion forces the entire pattern to be matched literally. </p> <p>The pattern will match if it matches any part of the string. If you want to force the pattern to match the entire string, anchor the pattern using the ‘<samp>^</samp>’ and ‘<samp>$</samp>’ regular expression operators. </p> <p>For example, the following will match a line (stored in the shell variable <code>line</code>) if there is a sequence of characters anywhere in the value consisting of any number, including zero, of characters in the <code>space</code> character class, immediately followed by zero or one instances of ‘<samp>a</samp>’, then a ‘<samp>b</samp>’: </p> <div class="example"> <pre class="example">[[ $line =~ [[:space:]]*(a)?b ]] +</pre> +</div> <p>That means values for <code>line</code> like ‘<samp>aab</samp>’, ‘<samp> aaaaaab</samp>’, ‘<samp>xaby</samp>’, and ‘<samp> ab</samp>’ will all match, as will a line containing a ‘<samp>b</samp>’ anywhere in its value. </p> <p>If you want to match a character that’s special to the regular expression grammar (‘<samp>^$|[]()\.*+?</samp>’), it has to be quoted to remove its special meaning. This means that in the pattern ‘<samp>xxx.txt</samp>’, the ‘<samp>.</samp>’ matches any character in the string (its usual regular expression meaning), but in the pattern ‘<samp>"xxx.txt"</samp>’, it can only match a literal ‘<samp>.</samp>’. </p> <p>Likewise, if you want to include a character in your pattern that has a special meaning to the regular expression grammar, you must make sure it’s not quoted. If you want to anchor a pattern at the beginning or end of the string, for instance, you cannot quote the ‘<samp>^</samp>’ or ‘<samp>$</samp>’ characters using any form of shell quoting. </p> <p>If you want to match ‘<samp>initial string</samp>’ at the start of a line, the following will work: </p> +<div class="example"> <pre class="example">[[ $line =~ ^"initial string" ]] +</pre> +</div> <p>but this will not: </p> +<div class="example"> <pre class="example">[[ $line =~ "^initial string" ]] +</pre> +</div> <p>because in the second example the ‘<samp>^</samp>’ is quoted and doesn’t have its usual special meaning. </p> <p>It is sometimes difficult to specify a regular expression properly without using quotes, or to keep track of the quoting used by regular expressions while paying attention to shell quoting and the shell’s quote removal. Storing the regular expression in a shell variable is often a useful way to avoid problems with quoting characters that are special to the shell. For example, the following is equivalent to the pattern used above: </p> <div class="example"> <pre class="example">pattern='[[:space:]]*(a)?b' +[[ $line =~ $pattern ]] +</pre> +</div> <p>Shell programmers should take special care with backslashes, since backslashes are used by both the shell and regular expressions to remove the special meaning from the following character. This means that after the shell’s word expansions complete (see <a href="shell-expansions">Shell Expansions</a>), any backslashes remaining in parts of the pattern that were originally not quoted can remove the special meaning of pattern characters. If any part of the pattern is quoted, the shell does its best to ensure that the regular expression treats those remaining backslashes as literal, if they appeared in a quoted portion. </p> <p>The following two sets of commands are <em>not</em> equivalent: </p> <div class="example"> <pre class="example">pattern='\.' + +[[ . =~ $pattern ]] +[[ . =~ \. ]] + +[[ . =~ "$pattern" ]] +[[ . =~ '\.' ]] +</pre> +</div> <p>The first two matches will succeed, but the second two will not, because in the second two the backslash will be part of the pattern to be matched. In the first two examples, the pattern passed to the regular expression parser is ‘<samp>\.</samp>’. The backslash removes the special meaning from ‘<samp>.</samp>’, so the literal ‘<samp>.</samp>’ matches. In the second two examples, the pattern passed to the regular expression parser has the backslash quoted (e.g., ‘<samp>\\\.</samp>’), which will not match the string, since it does not contain a backslash. If the string in the first examples were anything other than ‘<samp>.</samp>’, say ‘<samp>a</samp>’, the pattern would not match, because the quoted ‘<samp>.</samp>’ in the pattern loses its special meaning of matching any single character. </p> <p>Bracket expressions in regular expressions can be sources of errors as well, since characters that are normally special in regular expressions lose their special meanings between brackets. However, you can use bracket expressions to match special pattern characters without quoting them, so they are sometimes useful for this purpose. </p> <p>Though it might seem like a strange way to write it, the following pattern will match a ‘<samp>.</samp>’ in the string: </p> <div class="example"> <pre class="example">[[ . =~ [.] ]] +</pre> +</div> <p>The shell performs any word expansions before passing the pattern to the regular expression functions, so you can assume that the shell’s quoting takes precedence. As noted above, the regular expression parser will interpret any unquoted backslashes remaining in the pattern after shell expansion according to its own rules. The intention is to avoid making shell programmers quote things twice as much as possible, so shell quoting should be sufficient to quote special pattern characters where that’s necessary. </p> <p>The array variable <code>BASH_REMATCH</code> records which parts of the string matched the pattern. The element of <code>BASH_REMATCH</code> with index 0 contains the portion of the string matching the entire regular expression. Substrings matched by parenthesized subexpressions within the regular expression are saved in the remaining <code>BASH_REMATCH</code> indices. The element of <code>BASH_REMATCH</code> with index <var>n</var> is the portion of the string matching the <var>n</var>th parenthesized subexpression. </p> <p>Bash sets <code>BASH_REMATCH</code> in the global scope; declaring it as a local variable will lead to unexpected results. </p> <p>Expressions may be combined using the following operators, listed in decreasing order of precedence: </p> <dl compact> <dt><span><code>( <var>expression</var> )</code></span></dt> <dd> +<p>Returns the value of <var>expression</var>. This may be used to override the normal precedence of operators. </p> </dd> <dt><span><code>! <var>expression</var></code></span></dt> <dd> +<p>True if <var>expression</var> is false. </p> </dd> <dt><span><code><var>expression1</var> && <var>expression2</var></code></span></dt> <dd> +<p>True if both <var>expression1</var> and <var>expression2</var> are true. </p> </dd> <dt><span><code><var>expression1</var> || <var>expression2</var></code></span></dt> <dd><p>True if either <var>expression1</var> or <var>expression2</var> is true. </p></dd> </dl> <p>The <code>&&</code> and <code>||</code> operators do not evaluate <var>expression2</var> if the value of <var>expression1</var> is sufficient to determine the return value of the entire conditional expression. </p> +</dd> </dl><div class="_attribution"> + <p class="_attribution-p"> + Copyright © 2000, 2001, 2002, 2007, 2008 Free Software Foundation, Inc.<br>Licensed under the GNU Free Documentation License.<br> + <a href="https://www.gnu.org/software/bash/manual/html_node/Conditional-Constructs.html" class="_attribution-link">https://www.gnu.org/software/bash/manual/html_node/Conditional-Constructs.html</a> + </p> +</div> |
