Here's how to temporarily superseed environment variables for the execution of a
single command:
var=value var2=value2 Command Parm1 ... ParmN
Note: The semicolon character can be used to separate commands whenever a
newline would seem to be implied.
Inline File Data
Here's an example of passing inline file data to a command through the stdin file handle:
Command Parm1 ... ParmN <<*EOF
line1
line2 - $fred -
line3
*EOF
NextCommand
In this case, when "Command" runs, it will read the specified lines, 1 through 3. It will
not see the line containing "*EOF".
The characters "*EOF" are not special: any simple word can be used as the end-of-data signifier.
Note that the signifier is only interpreted as end-of-data if it appears in column 1 of the line.
Note that within the inline-data, variable expansion takes place. This means that $fred will be
replaced with the contents of the variable named "fred".
Statement Groups
Statements may be grouped together using either parentheses or curly braces. For example:
(
command
command
...
)
{
command
command
...
}
( cmd ; cmd ; ... )
{ cmd ; cmd ; ... }
The difference between parentheses and curly braces is as follows: A parenthetical statement group
is executed in a sub-shell, but a curly brace group is executed in the current shell. Note that
this difference applies to function bodies as well as to statement groups!
A statement group, of either stripe, is executed using the same set of standard file handles. This
means that a group can be used to redirect the standard input or output of the whole group of
commands in a single statement. For example, you can write this:
{ echo this; echo that ; echo the other; } >output.txt
Instead of writing this:
echo this >output.txt
echo that >>output.txt
echo the other >>output.txt
Statement groups are also used to define multi-statement conditionals for while loops and if statements.
Note that in brash you must use statement groups if multi-statement conditionals are require -- unlike
the bourne and brash shells.
Conditionals
There are 3 kinds of conditional statements:
The while and for statements are discussed in the next
section.
If statements have the following form:
if conditionCommand
then
commands
else
commands
fi
Where conditionCommand can be any of:
- a single program or script invocation, including parameters
- [ boolean expression ]
- (( arithmetic expression )) See Below
- ( command ; command ... )
- { command ; command ... }
Note: the semicolon in the above examples can be replaced with newlines.
Note also that in brash, the if-statement and while-statement only allow a single
conditional statement. The group operators, () or {}, can be used if multiple statements are
needed to properly define a condition.
Redirecting standard input and standard output is done after the fi
keyword:
if [ $x = $y ]
then
echo this goes to file.txt if the variable x equals the variable y
echo but if they are not equal, then file.txt becomes empty.
fi >file.txt
Looping Commands
There are two kinds of looping commands built into brash:
While Loops
Here are examples of using while loops:
while true
do
echo this will be repeatedly printed forever
done
while [ a = b ]
do
echo this will never be printed
done
while [ "$a" = "$b" ]
do
echo this will be printed forever if the variable a
echo equals the variable b
done
let i=0
while (( i < 100 ))
do
echo This will be repeated 100 times
let i++
done
while read line
do
echo This will be printed once for each line in the file
echo named file.txt
echo the text will be written to outputFile.txt not the screen
done outputFile.txt
.cat file.txt | while read line
do
echo So will this
done
For Loops
Here is an example of using a for loop to iterate over a list
of strings:
for f in 1 a b c d 13 22 91
do
echo f=$f
echo This line will be repeated 8 times
done
Here is an example of using a for loop to iterate over a list
of file names from the current directory:
for f in *
do
echo currentFileName = $f
echo This will be repeated once for each file
echo or directory in the current directory
done
Here is an example of using a for loop to iterate over a range
of numbers:
for (( i=0; i < 100; ++i ))
do
echo $i
echo This will be printed 100 times
done
Case Statements
Case statements are the mechanism by which a string can be checked to see if it matches a given
file name extension -- or other file name pattern, for that matter.
One way you could process files in a directory whose names match a given pattern is to use a
for-loop like this:
for f in *.c
do
echo $f
done
In this example the names of files ending in ".c" will be printed.
However, this example does the same thing -- and more:
for f in *
do
case "$f" in
*.c)
echo $f
;;
*.obj)
# do something else with obj files
;;
*.exe)
# do something else with executable files
;;
fred*tom*hank.d)
# do something else with files named fredtomhank.d or others
# like fredsusantomellenhank.d
# etc.
;;
*)
# handle all other file types
;;
esac
done
Note that you generally want to surround string expressions in the case line with double quotes
to prevent syntax errors caused by files whose names contain spaces.
Arithmetic Commands
Here are examples of arithmetic statements:
let i="47*91"
let b="i>19"
(( i=19; ))
for (( a=10; a<20; ++a ))
do
...
done
while (( i < 20 ))
do
...
done
Note: The less-than and greater-than operators lose their
file i/o redirection meaning in arithmetic statements (( ... )) but not in
let statements. Be careful to use quotes around these operators
in plain vanila let statements.
Generally, you should not use dollar signs, "$", in arithmetic command bodies.
You can, but it may not work the way you want. Particularly, if you use the
dollar sign on the left hand side of an equal operator, "=".
The variables used in arithmetic statements should be pure numbers. Anything else
may be mis-interpreted.
Reading Files
Here is how to read the stdin file, one line at a time:
while read line
do
process $line
done
Here is how to read the entire stdin file stream into an environment variable:
read -f varname
Newlines will remain embedded in the string stored in the variable.
Regular Expressions
Regular expressions are an important part of any script language. They allow you
to match patterns in character strings and to perform complex pattern-aware
string replacements.
However, the subject is fairly complex and won't be treated here. Use
google to find "basic regular expressions" document elsewhere. If you don't know what
sed and grep are, look them up too.
This section discusses the regular expression capabilities of brash.
Brash provides 2 ways of using regular expressions:
- the if statement has a test to determine if a string matches a regular expression.
- the builtin in command, .regex can both find and replace patterns using regular expressions.
if-statements and the regex test operator
When writing if statements, the following syntax can be used to check to see if a string
matches a regular expression:
string =~ regexPattern
A regexPattern is a string that is formatted according to the rules of basic regular expressions
(which are documented elsewhere on the web).
Here is a typical coding example:
.cat file | while read line
do
if [ "$line" =~ "fred.*susan.*bill" ]
then
echo found all 3 names in this line: $line
break
fi
done
In this example, a file is being read and each line is processed separately. Only lines that contain the
strings "fred", then "susan", then "bill", in order, are of interest. Note that fred, susan, and bill may
be widely separated on the line (by other characters) -- but only lines with all three in the correct order will pass the =~
test.
.regex
The .regex command combines a bunch of features into a single command:
- It reads files and processes all the lines
- It can print them all, or only the lines of interest -- as defined by a regular expression. See -m.
- It can perform regular expression substitutions on all lines of interest: See -p and -r.
- It can print line numbers and file names on each output line -- if so desired. See -f and -l
- It can simulate grep and parts of sed -- if you set the right options.
When reading all the lines in file, this command is dramatically faster than using an if statement inside a while loop.
But the only interpretation that can be done is to print or replace-string on the matching lines -- or both.
&& and ||
Semicolons can be used to separate commands which are all going to be executed in sequence -- just as if the semicolon
were a newline.
However, the && and || operators are also used to separate commands but they have a different meaning:
- The && operator is used to indicate that the second command will only execute if the first command exits with
a true exit code (i.e. zero).
- The || operator indicates that the second command will only execute if the first command executed with a fail
exit code (i.e. any non-zero value).
Here are some examples:
a && b # b only executes if a exits with true
c || d # d only executes if c exists with false
a || b || c || d # d only executes if a, b, and c all fail.
a && b && c # c only executes if both a and b exit with true.
Background Commands
Most commands execute immediately and the user is forced to wait for their completion.
However, it is possible to execute a command and have it detached from the console
so that the user can continue on executing other jobs.
Obviously, if the background command writes to the console, this will confuse the user,
so generally, when creating background jobs it is advisable to redirect their
standard streams into files. This is not a requirement however.
To launch a job in the background, do something like this:
command & # executes the command but leaves stdin, stdout, and stderr pointing to the console.
command nul: 2>&1 & # totally redirects the job away from the console.
To see what background jobs are still running, use the command jobs.
Return to the
TOP