{ code; } Command block
(code) Subshell
$'string' Quoting
${!var} Indirect Variable Reference
"'$var" | '"string' Char to Octal/Decimal/Hex
Variable substitution is generally characterized by using curly braces of the form
${var...}. There is an additional form ${#...} used for determining a number.
If var is followed by one or two forward slashes ${var/...} then the substitution is
of the form /pattern/replacement or /pattern drop if no /replacement given.
If var is followed by one or two octothorps ${var#...} then the substitution is of the the
form #pattern drop where pattern occurs at the beginning.
If var is followed by one or two percent signs ${var%...} then the substitution
is of the form %pattern drop where pattern occurs at the end.
If var is followed by a slash and then an octothorpe ${var/#...} then the substitution is of the
form /#pattern drop where a greedy match is formed at the beginning.
If var is followed by a slash and then a percent sign ${var/%...} then the substitution is of the
form /%pattern drop where a greedy match is formed at the end.
If the pattern is followed by /repl then a replacement is made where the matched pattern
was dropped
If var is followed by a colon ${var:...} then any of the chars - = ? or + then the substitution
is of the form where either var or the value following is used depending on the char following
the colon. If one of the chars is used without the colon then var must be nonnull as well
as set.
If var is followed by a colon and a digit ${var:n:m} then the substitution is of the form of a substring, starting at position n (0 based) and containing m characters or the remainder of the string if no m is given
For the form ${#...}, there are three constructs: ${#var} length of var, ${#$} and ${#@} number of positional parameters.
For the form ${!...}, there are two constructs which produce the same result: ${!prefix*} and ${!prefix@}. Both list the variables whose names begin with prefix
NOTE: Use the $'\xNN' syntax for non-printing characters.
${a} is the general form for dereferencing. The braces are normally optional, excepting arrays.
Here are the constructs:
Note that while ${var%%pat} and ${var/%pat} produce identical results
and that ${var##pat} and ${var/#pat} produce identical results there
is no equivalent ${var%%pat/repl} or ${var##pat/repl} so ${var/%pat/repl} and
${var/#pat/repl} must be used to replace the longest match and ${var/pat/repl}
must be used to replace the shortest match from the beginning. Note also that the
wildcard * is greedy when used with ${var/pat}, ${var/%pat} and there is no
way to replace the shortest match from the end using the * wildcard. For example
if a=ABCXYZABC and you want to replace the final ABC with 123 then
${a/%A?C/123}
works, producing ABCXYZ123 but
${a/%A*C/123}
produces 123 because of the greedy *. The obvious workaround is to simply chop the final ABC with ${a%A*} and then append the 123
${a%A*}123
Some examples: Assume a='Hello, World!' and b='' and c is unset
bar='Hello, World!'
foo=bar
echo ${!foo} # --> Hello, World!
baz=${!foo}
echo $baz # --> Hello, World!
This is a replacement for eval var2=\$$var1
var1=foo
foo=bar
eval var2=\$$var1
echo $var2 # --> bar
Each invocation of eval forces a re-evaluation of its arguments.
a='$b'
b='$c'
c=d
echo $a # $b
# First level.
eval echo $a # $c
# Second level.
eval eval echo $a # d
# Third level.
A simple use for an indirect variable reference
a='/etc/crontab'
ls $a # gives a directory listing of /etc/crontab
[ -s ${!a} ] && echo "$a exists and is not empty"
Here we are not testing a variable but instead we are
testing what the variable is pointing to
Syntax: set [options] [arg1 arg2 ...]
Example: set -- -1 -x
Explanation: -- turns off option processing so $1 is set to -1 and $2 is set to -x
Example: set -- *
Explanation: set the postitional parameters to the names of all the files in the current directory
Example: set --
Explanation: with no arguments, unset the positional parameters,
Words of the form $'string' are treated specially. The word expands to string,
with backslash-escaped characters replaced as specified by the ANSI C standard.
Backslash escape sequences, if present, are decoded as follows:
\a alert (bell)
\b backspace
\e an escape character
\f form feed
\n new line
\r carriage return
\t horizontal tab
\v vertical tab
\\ backslash
\' single quote
\nnn the eight-bit character whose value is the octal value nnn (one to three digits)
\xHH the eight-bit character whose value is the hexadecimal value HH (one or two hex digits)
\cx a control-x character
CR=$'\r' sets the variable CR to be a hex 0D (decimal 13)
LF=$'\n' sets the variable LF to be a hex 0A (decimal 10)
echo 'cat\ndog'
catndog
echo $'cat\ndog'
cat
dog
( execute in a subshell )
[ $a = 2 ] || (echo noa && echo xxx)
[ $a = 2 ] || { echo noa && echo xxx; }
Feed a block at the top with command output
(Beware the 2048 byte limit of temp files created by pipes)
Also be aware that you can't get variables out of this block
command | while read LINE; do echo $LINE done also command | while read WORD1 WORD2 REST; do do something with $WORD1 do something with $WORD2 do something with $REST done
Feed a block at the bottom with command output
while read LINE; do echo $LINE done < <(command)
The space between < and < is required
and this will not work with #!/bin/sh. use #!/bin/bash
Another form is useful to have script commands and data in the same file
while read a;do do something with $a done << EOL data line 1 data line 2 EOL
Feed a block at the top with file output
As above, you can't get variables out of this block
cat file | while read LINE; do echo $LINE done
To get variables:
cat /etc/passwd | ( IFS=: while read lognam pw id gp fname home sh; do echo $home \"$fname\" done )
Feed a block at the bottom with file output
while read LINE; do echo "$LINE" done < /etc/joe/joerc|grep -v "^#"|grep -v '^$'
This example code also ignores comment and blank lines
Using the line command instead of read
while LINE=$(/usr/bin/line); do echo "$LINE" done < /etc/joe/joerc|grep -v "^#"|grep -v '^$'
Using input file descriptors
exec 3<&0 # Associate stdin with fd3 exec 0> $INFILE # Redirect $INFILE to stdin while read LINE; do echo $LINE done exec 0<&3 # Restore stdin exec 3>&- # Close fd3
Using output file descriptors
exec 4<&1 # Associate stdout with fd4 exec 1> $OUTFILE # Redirect stdout to $OUTFILE while read LINE; do echo $LINE done < $INFILE exec 1<&4 # Restore stdout exec 4>&- # Close fd4
$ bar=3
$ foo=bar
$ echo ${!foo}
3
$ eval echo \$$foo
3
$ eval a=\$$foo
$ echo $a
3
See also Brace Expansion
a=(cat dog hat rat)
for key in ${!a[*]};do echo $key;done
0
1
2
3
for value in ${a[*]};do echo $value;done
cat
dog
hat
rat
a=("black cat" "hot dog")
for value in "${a[@]}";do echo $value;done
black cat
hot dog
for value in "${a[*]}";do echo $value;done
black cat hot dog
Command substitution allows the output of a command to
replace the command name. There are two forms:
$(command)
`command`
Bash performs the expansion by executing command and replacing the command substitution with the standard output of the command, with any trailing newlines deleted. Embedded newlines are not deleted, but they may be removed during word splitting. The command substitution $(cat file) can be replaced by the equivalent but faster $(< file).
If the substitution appears within double quotes, word splitting and filename expansion are not performed on the results.
echo -e $(cat now)
Now is the time For all good men To go to the aid Of their country.
echo -e "$(cat now)"
Now is the time
For all good men
To go to the aid
Of their country.
for LINE in "$(cat now)"; do echo -e x${LINE}x;done
xNow is the time For all good men To go to the aid Of their country.x
for LINE in $(cat now); do echo -e x${LINE}x;done
xNowx
xisx
xthex
xtimex
xForx
xallx
xgoodx
xmenx
xTox
xgox
xtox
xthex
xaidx
xOfx
xtheirx
xcountry.x
echo {a,b}{c,d} --> ac ad bc bd
echo {a..d}{e,f} --> ae af be bf ce cf de df
cat {file1,file2,file3} > combined_file # Concatenates the files file1, file2, and file3 into combined_file.
cp /usr/local/bin/file22.{txt,backup} # Copies "/usr/local/bin/file22.txt" to "/usr/local/bin/file22.backup"
file1='/bin/sh'
file2='/etc/crontab'
file3='/boot/grub/'
ls $file{1,2,3} # Lists the directories named by the three variables
See also Indirect Expansion
![]() |
This site best viewed with a browser |
| Warning: This is a Debian centric site and MAY contain peanuts. | |
| Many thanks to Debra Lynn and Ian Murdock for making Debian possible | |
| First created Apr 22, 2008 ~ Last revised December 07, 2011 |