?? basics-reviewed.bash
字號:
#!/bin/bash# basics-reviewed.bash# File extension == *.bash == specific to Bash# Copyright (c) Michael S. Zick, 2003; All rights reserved.# License: Use in any form, for any purpose.# Revision: $ID$## Edited for layout by M.C.# (author of the "Advanced Bash Scripting Guide")# This script tested under Bash versions 2.04, 2.05a and 2.05b.# It may not work with earlier versions.# This demonstration script generates one --intentional--#+ "command not found" error message. See line 394.# The current Bash maintainer, Chet Ramey, has fixed the items noted#+ for an upcoming version of Bash. ###-------------------------------------------### ### Pipe the output of this script to 'more' ### ###+ else it will scroll off the page. ### ### ### ### You may also redirect its output ### ###+ to a file for examination. ### ###-------------------------------------------#### Most of the following points are described at length in#+ the text of the foregoing "Advanced Bash Scripting Guide."# This demonstration script is mostly just a reorganized presentation.# -- msz# Variables are not typed unless otherwise specified.# Variables are named. Names must contain a non-digit.# File descriptor names (as in, for example: 2>&1)#+ contain ONLY digits.# Parameters and Bash array elements are numbered.# (Parameters are very similar to Bash arrays.)# A variable name may be undefined (null reference).unset VarNull# A variable name may be defined but empty (null contents).VarEmpty='' # Two, adjacent, single quotes.# A variable name my be defined and non-emptyVarSomething='Literal'# A variable may contain:# * A whole number as a signed 32-bit (or larger) integer# * A string# A variable may also be an array.# A string may contain embedded blanks and may be treated#+ as if it where a function name with optional arguments.# The names of variables and the names of functions#+ are in different namespaces.# A variable may be defined as a Bash array either explicitly or#+ implicitly by the syntax of the assignment statement.# Explicit:declare -a ArrayVar# The echo command is a built-in.echo $VarSomething# The printf command is a built-in.# Translate %s as: String-Formatprintf %s $VarSomething # No linebreak specified, none output.echo # Default, only linebreak output.# The Bash parser word breaks on whitespace.# Whitespace, or the lack of it is significant.# (This holds true in general; there are, of course, exceptions.)# Translate the DOLLAR_SIGN character as: Content-Of.# Extended-Syntax way of writing Content-Of:echo ${VarSomething}# The ${ ... } Extended-Syntax allows more than just the variable#+ name to be specified.# In general, $VarSomething can always be written as: ${VarSomething}.# Call this script with arguments to see the following in action.# Outside of double-quotes, the special characters @ and *#+ specify identical behavior.# May be pronounced as: All-Elements-Of.# Without specification of a name, they refer to the#+ pre-defined parameter Bash-Array.# Glob-Pattern referencesecho $* # All parameters to script or functionecho ${*} # Same# Bash disables filename expansion for Glob-Patterns.# Only character matching is active.# All-Elements-Of referencesecho $@ # Same as aboveecho ${@} # Same as above# Within double-quotes, the behavior of Glob-Pattern references#+ depends on the setting of IFS (Input Field Separator).# Within double-quotes, All-Elements-Of references behave the same.# Specifying only the name of a variable holding a string refers#+ to all elements (characters) of a string.# To specify an element (character) of a string,#+ the Extended-Syntax reference notation (see below) MAY be used.# Specifying only the name of a Bash array references#+ the subscript zero element,#+ NOT the FIRST DEFINED nor the FIRST WITH CONTENTS element.# Additional qualification is needed to reference other elements,#+ which means that the reference MUST be written in Extended-Syntax.# The general form is: ${name[subscript]}.# The string forms may also be used: ${name:subscript}#+ for Bash-Arrays when referencing the subscript zero element.# Bash-Arrays are implemented internally as linked lists,#+ not as a fixed area of storage as in some programming languages.# Characteristics of Bash arrays (Bash-Arrays):# --------------------------------------------# If not otherwise specified, Bash-Array subscripts begin with#+ subscript number zero. Literally: [0]# This is called zero-based indexing.#### If not otherwise specified, Bash-Arrays are subscript packed#+ (sequential subscripts without subscript gaps).#### Negative subscripts are not allowed.#### Elements of a Bash-Array need not all be of the same type.#### Elements of a Bash-Array may be undefined (null reference).# That is, a Bash-Array my be "subscript sparse."#### Elements of a Bash-Array may be defined and empty (null contents).#### Elements of a Bash-Array may contain:# * A whole number as a signed 32-bit (or larger) integer# * A string# * A string formated so that it appears to be a function name# + with optional arguments#### Defined elements of a Bash-Array may be undefined (unset).# That is, a subscript packed Bash-Array may be changed# + into a subscript sparse Bash-Array.#### Elements may be added to a Bash-Array by defining an element#+ not previously defined.#### For these reasons, I have been calling them "Bash-Arrays".# I'll return to the generic term "array" from now on.# -- msz# Demo time -- initialize the previously declared ArrayVar as a#+ sparse array.# (The 'unset ... ' is just documentation here.)unset ArrayVar[0] # Just for the recordArrayVar[1]=one # Unquoted literalArrayVar[2]='' # Defined, and emptyunset ArrayVar[3] # Just for the recordArrayVar[4]='four' # Quoted literal# Translate the %q format as: Quoted-Respecting-IFS-Rules.echoecho '- - Outside of double-quotes - -'###printf %q ${ArrayVar[*]} # Glob-Pattern All-Elements-Ofechoecho 'echo command:'${ArrayVar[*]}###printf %q ${ArrayVar[@]} # All-Elements-Ofechoecho 'echo command:'${ArrayVar[@]}# The use of double-quotes may be translated as: Enable-Substitution.# There are five cases recognized for the IFS setting.echoecho '- - Within double-quotes - Default IFS of space-tab-newline - -'IFS=$'\x20'$'\x09'$'\x0A' # These three bytes, #+ in exactly this order.printf %q "${ArrayVar[*]}" # Glob-Pattern All-Elements-Ofechoecho 'echo command:'"${ArrayVar[*]}"###printf %q "${ArrayVar[@]}" # All-Elements-Ofechoecho 'echo command:'"${ArrayVar[@]}"echoecho '- - Within double-quotes - First character of IFS is ^ - -'# Any printing, non-whitespace character should do the same.IFS='^'$IFS # ^ + space tab newline###printf %q "${ArrayVar[*]}" # Glob-Pattern All-Elements-Ofechoecho 'echo command:'"${ArrayVar[*]}"###printf %q "${ArrayVar[@]}" # All-Elements-Ofechoecho 'echo command:'"${ArrayVar[@]}"echoecho '- - Within double-quotes - Without whitespace in IFS - -'IFS='^:%!'###printf %q "${ArrayVar[*]}" # Glob-Pattern All-Elements-Ofechoecho 'echo command:'"${ArrayVar[*]}"###printf %q "${ArrayVar[@]}" # All-Elements-Ofechoecho 'echo command:'"${ArrayVar[@]}"echoecho '- - Within double-quotes - IFS set and empty - -'IFS=''###printf %q "${ArrayVar[*]}" # Glob-Pattern All-Elements-Ofechoecho 'echo command:'"${ArrayVar[*]}"###printf %q "${ArrayVar[@]}" # All-Elements-Ofechoecho 'echo command:'"${ArrayVar[@]}"echoecho '- - Within double-quotes - IFS undefined - -'unset IFS###printf %q "${ArrayVar[*]}" # Glob-Pattern All-Elements-Ofechoecho 'echo command:'"${ArrayVar[*]}"###printf %q "${ArrayVar[@]}" # All-Elements-Ofechoecho 'echo command:'"${ArrayVar[@]}"# Put IFS back to the default.# Default is exactly these three bytes.IFS=$'\x20'$'\x09'$'\x0A' # In exactly this order.# Interpretation of the above outputs:# A Glob-Pattern is I/O; the setting of IFS matters.#### An All-Elements-Of does not consider IFS settings.#### Note the different output using the echo command and the#+ quoted format operator of the printf command.# Recall:# Parameters are similar to arrays and have the similar behaviors.#### The above examples demonstrate the possible variations.# To retain the shape of a sparse array, additional script#+ programming is required.#### The source code of Bash has a routine to output the#+ [subscript]=value array assignment format.# As of version 2.05b, that routine is not used,#+ but that might change in future releases.# The length of a string, measured in non-null elements (characters):echoecho '- - Non-quoted references - -'echo 'Non-Null character count: '${#VarSomething}' characters.'# test='Lit'$'\x00''eral' # $'\x00' is a null character.# echo ${#test} # See that?# The length of an array, measured in defined elements,#+ including null content elements.echoecho 'Defined content count: '${#ArrayVar[@]}' elements.'# That is NOT the maximum subscript (4).# That is NOT the range of the subscripts (1 . . 4 inclusive).# It IS the length of the linked list.#### Both the maximum subscript and the range of the subscripts may#+ be found with additional script programming.# The length of a string, measured in non-null elements (characters):echoecho '- - Quoted, Glob-Pattern references - -'echo 'Non-Null character count: '"${#VarSomething}"' characters.'# The length of an array, measured in defined elements,#+ including null-content elements.echoecho 'Defined element count: '"${#ArrayVar[*]}"' elements.'# Interpretation: Substitution does not effect the ${# ... } operation.# Suggestion:# Always use the All-Elements-Of character#+ if that is what is intended (independence from IFS).# Define a simple function.# I include an underscore in the name#+ to make it distinctive in the examples below.#### Bash separates variable names and function names#+ in different namespaces.# The Mark-One eyeball isn't that advanced.###_simple() { echo -n 'SimpleFunc'$@ # Newlines are swallowed in} #+ result returned in any case.# The ( ... ) notation invokes a command or function.# The $( ... ) notation is pronounced: Result-Of.# Invoke the function _simpleechoecho '- - Output of function _simple - -'_simple # Try passing arguments.echo# or(_simple) # Try passing arguments.echoecho '- Is there a variable of that name? -'echo $_simple not defined # No variable by that name.# Invoke the result of function _simple (Error msg intended)###$(_simple) # Gives an error message:# line 394: SimpleFunc: command not found# ---------------------------------------echo#### The first word of the result of function _simple#+ is neither a valid Bash command nor the name of a defined function.#### This demonstrates that the output of _simple is subject to evaluation.#### Interpretation:# A function can be used to generate in-line Bash commands.# A simple function where the first word of result IS a bash command:###_print() { echo -n 'printf %q '$@}echo '- - Outputs of function _print - -'_print parm1 parm2 # An Output NOT A Command.echo$(_print parm1 parm2) # Executes: printf %q parm1 parm2 # See above IFS examples for the #+ various possibilities.echo$(_print $VarSomething) # The predictable result.echo# Function variables# ------------------echoecho '- - Function variables - -'# A variable may represent a signed integer, a string or an array.# A string may be used like a function name with optional arguments.# set -vx # Enable if desireddeclare -f funcVar #+ in namespace of functionsfuncVar=_print # Contains name of function.$funcVar parm1 # Same as _print at this point.echofuncVar=$(_print ) # Contains result of function.$funcVar # No input, No output.$funcVar $VarSomething # The predictable result.echofuncVar=$(_print $VarSomething) # $VarSomething replaced HERE.$funcVar # The expansion is part of theecho #+ variable contents.funcVar="$(_print $VarSomething)" # $VarSomething replaced HERE.$funcVar # The expansion is part of theecho #+ variable contents.# The difference between the unquoted and the double-quoted versions#+ above can be seen in the "protect_literal.sh" example.# The first case above is processed as two, unquoted, Bash-Words.# The second case above is processed as one, quoted, Bash-Word.# Delayed replacement# -------------------echoecho '- - Delayed replacement - -'funcVar="$(_print '$VarSomething')" # No replacement, single Bash-Word.eval $funcVar # $VarSomething replaced HERE.echoVarSomething='NewThing'eval $funcVar # $VarSomething replaced HERE.echo# Restore the original setting trashed above.VarSomething=Literal# There are a pair of functions demonstrated in the#+ "protect_literal.sh" and "unprotect_literal.sh" examples.# These are general purpose functions for delayed replacement literals#+ containing variables.# REVIEW:# ------# A string can be considered a Classic-Array of elements (characters).# A string operation applies to all elements (characters) of the string#+ (in concept, anyway).#### The notation: ${array_name[@]} represents all elements of the#+ Bash-Array: array_name.###
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -