Cari di Shell Script 
    Shell Script Linux Reference Manual
Daftar Isi
(Sebelumnya) 9. Beyond the Basics, Another ...11. Loops and Branches, Testin ... (Berikutnya)

Chapter 10. Manipulating Variables


10.1. Manipulating Strings

Bash supports a surprising number of string manipulation operations. Unfortunately, these tools lack a unified focus. Some are a subset of parameter substitution, and others fall under the functionality of the UNIX expr command. This results in inconsistent command syntax and overlap of functionality, not to mention confusion.

String Length

${#string}

expr length $string

These are the equivalent of strlen() in C.

expr "$string" : '.*'

stringZ=abcABC123ABCabcecho ${#stringZ} # 15echo `expr length $stringZ`  # 15echo `expr "$stringZ" : '.*'` # 15

Example 10-1. Inserting a blank line between paragraphs in a text file

#!/bin/bash# paragraph-space.sh# Ver. 2.1, Reldate 29Jul12 [fixup]# Inserts a blank line between paragraphs of a single-spaced text file.# Usage: $0 <FILENAMEMINLEN=60 # Change this value? It's a judgment call.#  Assume lines shorter than $MINLEN characters ending in a period#+ terminate a paragraph. See exercises below.while read line  # For as many lines as the input file has ...do  echo "$line"   # Output the line itself.  len=${#line}  if [[ "$len" -lt "$MINLEN" && "$line" =~ [*{.}]$ ]]# if [[ "$len" -lt "$MINLEN" && "$line" =~ [*.] ]]# An update to Bash broke the previous version of this script. Ouch!# Thank you, Halim Srama, for pointing this out and suggesting a fix. then echo #  Add a blank line immediately  fi #+ after a short line terminated by a period.doneexit# Exercises:# ---------#  1) The script usually inserts a blank line at the end#+ of the target file. Fix this.#  2) Line 17 only considers periods as sentence terminators.# Modify this to include other common end-of-sentence characters,#+ such as ?, !, and ".

Length of Matching Substring at Beginning of String

expr match "$string" '$substring'

$substring is a regular expression.

expr "$string" : '$substring'

$substring is a regular expression.

stringZ=abcABC123ABCabc#   |------|#   12345678echo `expr match "$stringZ" 'abc[A-Z]*.2'`   # 8echo `expr "$stringZ" : 'abc[A-Z]*.2'`   # 8

Index

expr index $string $substring

Numerical position in $string of first character in $substring that matches.

stringZ=abcABC123ABCabc#   123456 ...echo `expr index "$stringZ" C12` # 6 # C position.echo `expr index "$stringZ" 1c`  # 3# 'c' (in #3 position) matches before '1'.

This is the near equivalent of strchr() in C.

Substring Extraction

${string:position}

Extracts substring from $string at $position.

If the $string parameter is "*" or "@", then this extracts the positional parameters, [1] starting at $position.

${string:position:length}

Extracts $length characters of substring from $string at $position.

stringZ=abcABC123ABCabc#   0123456789.....#   0-based indexing.echo ${stringZ:0} # abcABC123ABCabcecho ${stringZ:1} # bcABC123ABCabcecho ${stringZ:7} # 23ABCabcecho ${stringZ:7:3}  # 23A # Three characters of substring.# Is it possible to index from the right end of the string? echo ${stringZ:-4}   # abcABC123ABCabc# Defaults to full string, as in ${parameter:-default}.# However . . .echo ${stringZ:(-4)} # Cabc echo ${stringZ: -4}  # Cabc# Now, it works.# Parentheses or added space "escape" the position parameter.# Thank you, Dan Jacobson, for pointing this out.

The position and length arguments can be "parameterized," that is, represented as a variable, rather than as a numerical constant.

Example 10-2. Generating an 8-character "random" string

#!/bin/bash# rand-string.sh# Generating an 8-character "random" string.if [ -n "$1" ]  #  If command-line argument present,then #+ then set start-string to it.  str0="$1" else #  Else use PID of script as start-string.  str0="$$" fiPOS=2  # Starting from position 2 in the string.LEN=8  # Extract eight characters.str1=$( echo "$str0" | md5sum | md5sum )#  Doubly scramble ^^^^^^   ^^^^^^#+ by piping and repiping to md5sum.randstring="${str1:$POS:$LEN}" # Can parameterize ^^^^ ^^^^echo "$randstring" exit $?# bozo$ ./rand-string.sh my-password# 1bdd88c4#  No, this is is not recommended#+ as a method of generating hack-proof passwords.

If the $string parameter is "*" or "@", then this extracts a maximum of $length positional parameters, starting at $position.

echo ${*:2}  # Echoes second and following positional parameters.echo ${@:2}  # Same as above.echo ${*:2:3} # Echoes three positional parameters, starting at second.

expr substr $string $position $length

Extracts $length characters from $string starting at $position.

stringZ=abcABC123ABCabc#   123456789......#   1-based indexing.echo `expr substr $stringZ 1 2`  # abecho `expr substr $stringZ 4 3`  # ABC

expr match "$string" '($substring)'

Extracts $substring at beginning of $string, where $substring is a regular expression.

expr "$string" : '($substring)'

Extracts $substring at beginning of $string, where $substring is a regular expression.

stringZ=abcABC123ABCabc#   ======= echo `expr match "$stringZ" '(.[b-c]*[A-Z]..[0-9])'`   # abcABC1echo `expr "$stringZ" : '(.[b-c]*[A-Z]..[0-9])'`   # abcABC1echo `expr "$stringZ" : '(.......)'`   # abcABC1# All of the above forms give an identical result.

expr match "$string" '.*($substring)'

Extracts $substring at end of $string, where $substring is a regular expression.

expr "$string" : '.*($substring)'

Extracts $substring at end of $string, where $substring is a regular expression.

stringZ=abcABC123ABCabc# ======echo `expr match "$stringZ" '.*([A-C][A-C][A-C][a-c]*)'` # ABCabcecho `expr "$stringZ" : '.*(......)'`   # ABCabc

Substring Removal

${string#substring}

Deletes shortest match of $substring from front of $string.

${string##substring}

Deletes longest match of $substring from front of $string.

stringZ=abcABC123ABCabc#   |----|  shortest#   |----------| longestecho ${stringZ#a*C}  # 123ABCabc# Strip out shortest match between 'a' and 'C'.echo ${stringZ##a*C} # abc# Strip out longest match between 'a' and 'C'.# You can parameterize the substrings.X='a*C'echo ${stringZ#$X}  # 123ABCabcecho ${stringZ##$X} # abc # As above.

${string%substring}

Deletes shortest match of $substring from back of $string.

For example:

# Rename all filenames in $PWD with "TXT" suffix to a "txt" suffix.# For example, "file1.TXT" becomes "file1.txt" . . .SUFF=TXTsuff=txtfor i in $(ls *.$SUFF)do  mv -f $i ${i%.$SUFF}.$suff  #  Leave unchanged everything *except* the shortest pattern match  #+ starting from the right-hand-side of the variable $i . . .done ### This could be condensed into a "one-liner" if desired.# Thank you, Rory Winston.

${string%%substring}

Deletes longest match of $substring from back of $string.

stringZ=abcABC123ABCabc# || shortest# |------------| longestecho ${stringZ%b*c}  # abcABC123ABCa# Strip out shortest match between 'b' and 'c', from back of $stringZ.echo ${stringZ%%b*c} # a# Strip out longest match between 'b' and 'c', from back of $stringZ.

This operator is useful for generating filenames.

Example 10-3. Converting graphic file formats, with filename change

#!/bin/bash#  cvt.sh:#  Converts all the MacPaint image files in a directory to "pbm" format.#  Uses the "macptopbm" binary from the "netpbm" package,#+ which is maintained by Brian Henderson ([email protected]).#  Netpbm is a standard part of most Linux distros.OPERATION=macptopbmSUFFIX=pbm  # New filename suffix. if [ -n "$1" ]then  directory=$1  # If directory name given as a script argument...else  directory=$PWD # Otherwise use current working directory.fi #  Assumes all files in the target directory are MacPaint image files,#+ with a ".mac" filename suffix.for file in $directory/* # Filename globbing.do  filename=${file%.*c}  #  Strip ".mac" suffix off filename #+ ('.*c' matches everything #+ between '.' and 'c', inclusive).  $OPERATION $file > "$filename.$SUFFIX" # Redirect conversion to new filename.  rm -f $file   # Delete original files after converting. echo "$filename.$SUFFIX"  # Log what is happening to stdout.doneexit 0# Exercise:# --------#  As it stands, this script converts *all* the files in the current#+ working directory.#  Modify it to work *only* on files with a ".mac" suffix.

Example 10-4. Converting streaming audio files to ogg

#!/bin/bash# ra2ogg.sh: Convert streaming audio files (*.ra) to ogg.# Uses the "mplayer" media player program:#  http://www.mplayerhq.hu/homepage# Uses the "ogg" library and "oggenc":#  http://www.xiph.org/## This script may need appropriate codecs installed, such as sipr.so ...# Possibly also the compat-libstdc++ package.OFILEPREF=${1%%ra}  # Strip off the "ra" suffix.OFILESUFF=wav   # Suffix for wav file.OUTFILE="$OFILEPREF""$OFILESUFF" E_NOARGS=85if [ -z "$1" ]  # Must specify a filename to convert.then  echo "Usage: `basename $0` [filename]"   exit $E_NOARGSfi##########################################################################mplayer "$1" -ao pcm:file=$OUTFILEoggenc "$OUTFILE"  # Correct file extension automatically added by oggenc.##########################################################################rm "$OUTFILE"  # Delete intermediate *.wav file.   # If you want to keep it, comment out above line.exit $?#  Note:#  ----#  On a Website, simply clicking on a *.ram streaming audio file#+ usually only downloads the URL of the actual *.ra audio file.#  You can then use "wget" or something similar#+ to download the *.ra file itself.#  Exercises:#  ---------#  As is, this script converts only *.ra filenames.#  Add flexibility by permitting use of *.ram and other filenames.##  If you're really ambitious, expand the script#+ to do automatic downloads and conversions of streaming audio files.#  Given a URL, batch download streaming audio files (using "wget")#+ and convert them on the fly.

A simple emulation of getopt using substring-extraction constructs.

Example 10-5. Emulating getopt

#!/bin/bash# getopt-simple.sh# Author: Chris Morgan# Used in the ABS Guide with permission.getopt_simple(){ echo "getopt_simple()" echo "Parameters are '$*'" until [ -z "$1" ] do  echo "Processing parameter of: '$1'"   if [ ${1:0:1} = '/' ]  then  tmp=${1:1}   # Strip off leading '/' . . .  parameter=${tmp%%=*} # Extract name.  value=${tmp##*=} # Extract value.  echo "Parameter: '$parameter', value: '$value'"   eval $parameter=$value  fi  shift done}# Pass all options to getopt_simple().getopt_simple $*echo "test is '$test'" echo "test2 is '$test2'" exit 0  # See also, UseGetOpt.sh, a modified version of this script.---sh getopt_example.sh /test=value1 /test2=value2Parameters are '/test=value1 /test2=value2'Processing parameter of: '/test=value1'Parameter: 'test', value: 'value1'Processing parameter of: '/test2=value2'Parameter: 'test2', value: 'value2'test is 'value1'test2 is 'value2'

Substring Replacement

${string/substring/replacement}

Replace first match of $substring with $replacement. [2]

${string//substring/replacement}

Replace all matches of $substring with $replacement.

stringZ=abcABC123ABCabcecho ${stringZ/abc/xyz}   # xyzABC123ABCabc  # Replaces first match of 'abc' with 'xyz'.echo ${stringZ//abc/xyz}  # xyzABC123ABCxyz  # Replaces all matches of 'abc' with # 'xyz'.echo  ---------------echo "$stringZ"   # abcABC123ABCabcecho  ---------------  # The string itself is not altered!# Can the match and replacement strings be parameterized?match=abcrepl=000echo ${stringZ/$match/$repl}  # 000ABC123ABCabc#  ^  ^ ^^^echo ${stringZ//$match/$repl} # 000ABC123ABC000# Yes!  ^  ^ ^^^ ^^^echo# What happens if no $replacement string is supplied?echo ${stringZ/abc}   # ABC123ABCabcecho ${stringZ//abc}  # ABC123ABC# A simple deletion takes place.

${string/#substring/replacement}

If $substring matches front end of $string, substitute $replacement for $substring.

${string/%substring/replacement}

If $substring matches back end of $string, substitute $replacement for $substring.

stringZ=abcABC123ABCabcecho ${stringZ/#abc/XYZ}  # XYZABC123ABCabc  # Replaces front-end match of 'abc' with 'XYZ'.echo ${stringZ/%abc/XYZ}  # abcABC123ABCXYZ  # Replaces back-end match of 'abc' with 'XYZ'.

10.1.1. Manipulating strings using awk

A Bash script may invoke the string manipulation facilities of awk as an alternative to using its built-in operations.

Example 10-6. Alternate ways of extracting and locating substrings

#!/bin/bash# substring-extraction.shString=23skidoo1#  012345678 Bash#  123456789 awk# Note different string indexing system:# Bash numbers first character of string as 0.# Awk  numbers first character of string as 1.echo ${String:2:4} # position 3 (0-1-2), 4 characters long # skid# The awk equivalent of ${string:pos:length} is substr(string,pos,length).echo | awk '{ print substr("'"${String}"'",3,4)  # skid}'#  Piping an empty "echo" to awk gives it dummy input,#+ and thus makes it unnecessary to supply a filename.echo "----" # And likewise:echo | awk '{ print index("'"${String}"'", "skid")  # 3}   # (skid starts at position 3)'   # The awk equivalent of "expr index" ...exit 0

10.1.2. Further Reference

For more on string manipulation in scripts, refer to Section 10.2 and the relevant section of the expr command listing.

Script examples:

  • Example 16-9

  • Example 10-9

  • Example 10-10

  • Example 10-11

  • Example 10-13

  • Example A-36

  • Example A-41

  • Notes

    [1]

    This applies to either command-line arguments or parameters passed to a function.

    [2]

    Note that $substring and $replacement may refer to either literal strings or variables, depending on context. See the first usage example.


    10.2. Parameter Substitution

    Manipulating and/or expanding variables

    ${parameter}

    Same as $parameter, i.e., value of the variable parameter. In certain contexts, only the less ambiguous ${parameter} form works.

    May be used for concatenating variables with strings.

    your_id=${USER}-on-${HOSTNAME}echo "$your_id" #echo "Old $PATH = $PATH" PATH=${PATH}:/opt/bin  # Add /opt/bin to $PATH for duration of script.echo "New $PATH = $PATH"

    ${parameter-default}, ${parameter:-default}

    If parameter not set, use default.

    var1=1var2=2# var3 is unset.echo ${var1-$var2}   # 1echo ${var3-$var2}   # 2#   ^  Note the $ prefix.echo ${username-`whoami`}# Echoes the result of `whoami`, if variable $username is still unset.

    ${parameter-default} and ${parameter:-default} are almost equivalent. The extra : makes a difference only when parameter has been declared, but is null.

    #!/bin/bash# param-sub.sh#  Whether a variable has been declared#+ affects triggering of the default option#+ even if the variable is null.username0=echo "username0 has been declared, but is set to null." echo "username0 = ${username0-`whoami`}" # Will not echo.echoecho username1 has not been declared.echo "username1 = ${username1-`whoami`}" # Will echo.username2=echo "username2 has been declared, but is set to null." echo "username2 = ${username2:-`whoami`}" # ^# Will echo because of :- rather than just - in condition test.# Compare to first instance, above.## Once again:variable=# variable has been declared, but is set to null.echo "${variable-0}" # (no output)echo "${variable:-1}"   # 1#   ^unset variableecho "${variable-2}" # 2echo "${variable:-3}"   # 3exit 0

    The default parameter construct finds use in providing "missing" command-line arguments in scripts.

    DEFAULT_FILENAME=generic.datafilename=${1:-$DEFAULT_FILENAME}#  If not otherwise specified, the following command block operates#+ on the file "generic.data".#  Begin-Command-Block#  ...#  ...#  ...#  End-Command-Block#  From "hanoi2.bash" example:DISKS=${1:-E_NOPARAM}   # Must specify how many disks.#  Set $DISKS to $1 command-line-parameter,#+ or to $E_NOPARAM if that is unset.

    See also Example 3-4, Example 31-2, and Example A-6.

    Compare this method with using an and list to supply a default command-line argument.

    ${parameter=default}, ${parameter:=default}

    If parameter not set, set it to default.

    Both forms nearly equivalent. The : makes a difference only when $parameter has been declared and is null, [1] as above.

    echo ${var=abc}   # abcecho ${var=xyz}   # abc# $var had already been set to abc, so it did not change.

    ${parameter+alt_value}, ${parameter:+alt_value}

    If parameter set, use alt_value, else use null string.

    Both forms nearly equivalent. The : makes a difference only when parameter has been declared and is null, see below.

    echo "###### ${parameter+alt_value} ########" echoa=${param1+xyz}echo "a = $a"  # a =param2=a=${param2+xyz}echo "a = $a"  # a = xyzparam3=123a=${param3+xyz}echo "a = $a"  # a = xyzechoecho "###### ${parameter:+alt_value} ########" echoa=${param4:+xyz}echo "a = $a"  # a =param5=a=${param5:+xyz}echo "a = $a"  # a =# Different result from   a=${param5+xyz}param6=123a=${param6:+xyz}echo "a = $a"  # a = xyz

    ${parameter?err_msg}, ${parameter:?err_msg}

    If parameter set, use it, else print err_msg and abort the script with an exit status of 1.

    Both forms nearly equivalent. The : makes a difference only when parameter has been declared and is null, as above.

    Example 10-7. Using parameter substitution and error messages

    #!/bin/bash#  Check some of the system's environmental variables.#  This is good preventative maintenance.#  If, for example, $USER, the name of the person at the console, is not set,#+ the machine will not recognize you.: ${HOSTNAME?} ${USER?} ${HOME?} ${MAIL?}  echo  echo "Name of the machine is $HOSTNAME."   echo "You are $USER."   echo "Your home directory is $HOME."   echo "Your mail INBOX is located in $MAIL."   echo  echo "If you are reading this message,"   echo "critical environmental variables have been set."   echo  echo# ------------------------------------------------------#  The ${variablename?} construction can also check#+ for variables set within the script.ThisVariable=Value-of-ThisVariable#  Note, by the way, that string variables may be set#+ to characters disallowed in their names.: ${ThisVariable?}echo "Value of ThisVariable is $ThisVariable".echo; echo: ${ZZXy23AB?"ZZXy23AB has not been set."}#  Since ZZXy23AB has not been set,#+ then the script terminates with an error message.# You can specify the error message.# : ${variablename?"ERROR MESSAGE"}# Same result with:   dummy_variable=${ZZXy23AB?}# dummy_variable=${ZZXy23AB?"ZXy23AB has not been set."}## echo ${ZZXy23AB?} >/dev/null#  Compare these methods of checking whether a variable has been set#+ with "set -u" . . .echo "You will not see this message, because script already terminated." HERE=0exit $HERE   # Will NOT exit here.# In fact, this script will return an exit status (echo $?) of 1.

    Example 10-8. Parameter substitution and "usage" messages

    #!/bin/bash# usage-message.sh: ${1?"Usage: $0 ARGUMENT"}#  Script exits here if command-line parameter absent,#+ with following error message.# usage-message.sh: 1: Usage: usage-message.sh ARGUMENTecho "These two lines echo only if command-line parameter given." echo "command-line parameter = "$1"" exit 0  # Will exit here only if command-line parameter present.# Check the exit status, both with and without command-line parameter.# If command-line parameter present, then "$?" is 0.# If not, then "$?" is 1.

    Parameter substitution and/or expansion. The following expressions arethe complement to the matchin exprstring operations (see Example 16-9).These particular ones are used mostly in parsing filepath names.

    Variable length / Substring removal

    ${#var}

    String length (number of characters in $var). For an array, ${#array} is the length of the first element in the array.

    Exceptions:

    • ${#*} and ${#@} give the number of positional parameters.

    • For an array, ${#array[*]} and ${#array[@]} give the number of elements in the array.

    Example 10-9. Length of a variable

    #!/bin/bash# length.shE_NO_ARGS=65if [ $# -eq 0 ]  # Must have command-line args to demo script.then  echo "Please invoke this script with one or more command-line arguments."   exit $E_NO_ARGSfi  var01=abcdEFGH28ijecho "var01 = ${var01}" echo "Length of var01 = ${#var01}" # Now, let's try embedding a space.var02="abcd EFGH28ij" echo "var02 = ${var02}" echo "Length of var02 = ${#var02}" echo "Number of command-line arguments passed to script = ${#@}" echo "Number of command-line arguments passed to script = ${#*}" exit 0
    ${var#Pattern}, ${var##Pattern}

    ${var#Pattern} Remove from $var the shortest part of $Pattern that matches the front end of $var.

    ${var##Pattern} Remove from $var the longest part of $Pattern that matches the front end of $var.

    A usage illustration from Example A-7:

    # Function from "days-between.sh" example.# Strips leading zero(s) from argument passed.strip_leading_zero () #  Strip possible leading zero(s){ #+ from argument passed.  return=${1#0}   #  The "1" refers to "$1" -- passed arg.} #  The "0" is what to remove from "$1" -- strips zeros.

    Manfred Schwarb's more elaborate variation of theabove:

    strip_leading_zero2 () # Strip possible leading zero(s), since otherwise{  # Bash will interpret such numbers as octal values.  shopt -s extglob # Turn on extended globbing.  local val=${1##+(0)} # Use local variable, longest matching series of 0's.  shopt -u extglob # Turn off extended globbing.  _strip_leading_zero2=${val:-0}   # If input was 0, return 0 instead of "".}

    Another usage illustration:

    echo `basename $PWD` # Basename of current working directory.echo "${PWD##*/}"   # Basename of current working directory.echoecho `basename $0`  # Name of script.echo $0 # Name of script.echo "${0##*/}" # Name of script.echofilename=test.dataecho "${filename##*.}"  # data # Extension of filename.

    ${var%Pattern}, ${var%%Pattern}

    ${var%Pattern} Remove from $var the shortest part of $Pattern that matches the back end of $var.

    ${var%%Pattern} Remove from $var the longest part of $Pattern that matches the back end of $var.

    Version 2 of Bash added additional options.

    Example 10-10. Pattern matching in parameter substitution

    #!/bin/bash# patt-matching.sh# Pattern matching  using the # ## % %% parameter substitution operators.var1=abcd12345abc6789pattern1=a*c  # * (wild card) matches everything between a - c.echoecho "var1 = $var1"   # abcd12345abc6789echo "var1 = ${var1}" # abcd12345abc6789  # (alternate form)echo "Number of characters in ${var1} = ${#var1}" echoecho "pattern1 = $pattern1"   # a*c  (everything between 'a' and 'c')echo "--------------" echo '${var1#$pattern1}  =' "${var1#$pattern1}" # d12345abc6789# Shortest possible match, strips out first 3 characters  abcd12345abc6789# ^^^^^   |-|echo '${var1##$pattern1} =' "${var1##$pattern1}"   #  6789  # Longest possible match, strips out first 12 characters  abcd12345abc6789# ^^^^^ |----------|echo; echo; echopattern2=b*9 # everything between 'b' and '9'echo "var1 = $var1" # Still  abcd12345abc6789echoecho "pattern2 = $pattern2" echo "--------------" echo '${var1%pattern2}  =' "${var1%$pattern2}" # abcd12345a# Shortest possible match, strips out last 6 characters  abcd12345abc6789# ^^^^ |----|echo '${var1%%pattern2} =' "${var1%%$pattern2}" # a# Longest possible match, strips out last 12 characters  abcd12345abc6789# ^^^^ |-------------|# Remember, # and ## work from the left end (beginning) of string,#   % and %% work from the right end.echoexit 0

    Example 10-11. Renaming file extensions:

    #!/bin/bash# rfe.sh: Renaming file extensions.## rfe old_extension new_extension## Example:# To rename all *.gif files in working directory to *.jpg,#  rfe gif jpgE_BADARGS=65case $# in  0|1) # The vertical bar means "or" in this context.  echo "Usage: `basename $0` old_file_suffix new_file_suffix"   exit $E_BADARGS  # If 0 or 1 arg, then bail out.  ;esacfor filename in *.$1# Traverse list of files ending with 1st argument.do  mv $filename ${filename%$1}$2  #  Strip off part of filename matching 1st argument,  #+ then append 2nd argument.doneexit 0

    Variable expansion / Substring replacement

    These constructs have been adopted from ksh.

    ${var:pos}

    Variable var expanded, starting from offset pos.

    ${var:pos:len}

    Expansion to a max of len characters of variable var, from offset pos. See Example A-13 for an example of the creative use of this operator.

    ${var/Pattern/Replacement}

    First match of Pattern, within var replaced with Replacement.

    If Replacement is omitted, then the first match of Pattern is replaced by nothing, that is, deleted.

    ${var//Pattern/Replacement}

    Global replacement. All matches of Pattern, within var replaced with Replacement.

    As above, if Replacement is omitted, then all occurrences of Pattern are replaced by nothing, that is, deleted.

    Example 10-12. Using pattern matching to parse arbitrary strings

    #!/bin/bashvar1=abcd-1234-defgecho "var1 = $var1" t=${var1#*-*}echo "var1 (with everything, up to and including first - stripped out) = $t" #  t=${var1#*-}  works just the same,#+ since # matches the shortest string,#+ and * matches everything preceding, including an empty string.# (Thanks, Stephane Chazelas, for pointing this out.)t=${var1##*-*}echo "If var1 contains a "-", returns empty string...   var1 = $t" t=${var1%*-*}echo "var1 (with everything from the last - on stripped out) = $t" echo# -------------------------------------------path_name=/home/bozo/ideas/thoughts.for.today# -------------------------------------------echo "path_name = $path_name" t=${path_name##/*/}echo "path_name, stripped of prefixes = $t" # Same effect as   t=`basename $path_name` in this particular case.#  t=${path_name%/}; t=${t##*/}   is a more general solution,#+ but still fails sometimes.#  If $path_name ends with a newline, then `basename $path_name` will not work,#+ but the above expression will.# (Thanks, S.C.)t=${path_name%/*.*}# Same effect as   t=`dirname $path_name`echo "path_name, stripped of suffixes = $t" # These will fail in some cases, such as "../", "/foo////", # "foo/", "/".#  Removing suffixes, especially when the basename has no suffix,#+ but the dirname does, also complicates matters.# (Thanks, S.C.)echot=${path_name:11}echo "$path_name, with first 11 chars stripped off = $t" t=${path_name:11:5}echo "$path_name, with first 11 chars stripped off, length 5 = $t" echot=${path_name/bozo/clown}echo "$path_name with "bozo" replaced  by "clown" = $t" t=${path_name/today/}echo "$path_name with "today" deleted = $t" t=${path_name//o/O}echo "$path_name with all o's capitalized = $t" t=${path_name//o/}echo "$path_name with all o's deleted = $t" exit 0
    ${var/#Pattern/Replacement}

    If prefix of var matches Pattern, then substitute Replacement for Pattern.

    ${var/%Pattern/Replacement}

    If suffix of var matches Pattern, then substitute Replacement for Pattern.

    Example 10-13. Matching patterns at prefix or suffix of string

    #!/bin/bash# var-match.sh:# Demo of pattern replacement at prefix / suffix of string.v0=abc1234zip1234abc # Original variable.echo "v0 = $v0" # abc1234zip1234abcecho# Match at prefix (beginning) of string.v1=${v0/#abc/ABCDEF} # abc1234zip1234abc # |-|echo "v1 = $v1" # ABCDEF1234zip1234abc # |----|# Match at suffix (end) of string.v2=${v0/%abc/ABCDEF} # abc1234zip123abc #  |-|echo "v2 = $v2" # abc1234zip1234ABCDEF #   |----|echo#  ----------------------------------------------------#  Must match at beginning / end of string,#+ otherwise no replacement results.#  ----------------------------------------------------v3=${v0/#123/000}   # Matches, but not at beginning.echo "v3 = $v3" # abc1234zip1234abc # NO REPLACEMENT.v4=${v0/%123/000}   # Matches, but not at end.echo "v4 = $v4" # abc1234zip1234abc # NO REPLACEMENT.exit 0
    ${!varprefix*}, ${!varprefix@}

    Matches names of all previously declared variables beginning with varprefix.

    # This is a variation on indirect reference, but with a * or @.# Bash, version 2.04, adds this feature.xyz23=whateverxyz24=a=${!xyz*} #  Expands to *names* of declared variables# ^ ^   ^   + beginning with "xyz".echo "a = $a"  #  a = xyz23 xyz24a=${!xyz@} #  Same as above.echo "a = $a"  #  a = xyz23 xyz24echo "---" abc23=something_elseb=${!abc*}echo "b = $b"  #  b = abc23c=${!b} #  Now, the more familiar type of indirect reference.echo $c #  something_else

    Notes

    [1]

    If $parameter is null in a non-interactive script, it will terminate with a 127 exit status (the Bash error code for "command not found").


    Copyright © 2000, by Mendel Cooper <[email protected]>
    (Sebelumnya) 9. Beyond the Basics, Another ...11. Loops and Branches, Testin ... (Berikutnya)