读书笔记 - Beginning Linux Programming - Chapter 2 Shell Programming

Shell

 

What is Shell

Just like the batch file in windows, but more powerful

 

Pipes and redirection

 

Redirecting Output

$ ls -l > lsoutput.txt

Write into isoutput.txt
$ ps >> lsoutput.txt

Append to the file

$ kill -HUP 1234 >killout.txt 2>killerr.txt
Kill the process and sperate the output and error info into different files

$ kill -1 1234 >killouterr.txt 2>&1

Kill the process and write the error info in to the same file as output

 

Redirecting Input

$ more < killout.txt

 

Pipes

You can connect processes using the pipe operator ( | ).In Linux, unlike in MS-DOS, processes connected by pipes can run simultaneously and are automatically rescheduled as data flows between them
$ ps | sort > pssort.out
$ ps | sort | more
$ ps –xo comm | sort | uniq | grep -v sh | more

 

The Shell as a Programming Language

$ for file in *
> do
> if grep -l POSIX $file
> then
> more $file
> fi
> done
Note how the normal $ shell prompt changes to a > when the shell is expecting further input. You can type away, letting the shell decide when you’re finished, and the script will execute immediately.

 

widl cards

$ ls my_{finger,toe}s

 

Experienced Linux users would probably perform this simple operation in a much more efficient way,
perhaps with a command such as
$ more `grep -l POSIX *`
or the synonymous construction
$ more $(grep -l POSIX *)
In addition,
$ grep -l POSIX * | more

 

Creating a script

#!/bin/sh
#first
#This file looks through all the files in the current
#directory for the string POSIX, and then prints the names of
t#hose files to the standard output.
for file in *
do
if grep -q POSIX $file
then
echo $file
fi
done
exit 0

 

#! characters tell the system that the argument that follows on the line is the program to be used to execute this file. In this case, /bin/sh is the default shell program.

 

The exit command ensures that the script returns a sensible exit code

 

Lnux, and UNIX in general, rarely makes use of the filename extension to determine the type of a file

 

Making a script executable

 

1. $ /bin/sh first

2. $ chmod +x first


#cp first /usr/local/bin
#chown root /usr/local/bin/first
#chgrp root /usr/local/bin/first
#chmod 755 /usr/local/bin/first

 

Shell Syntax

 

Varaibles

You don’t usually declare variables in the shell before using them. Instead, you create them by simply
using them (for example, when you assign an initial value to them). By default, all variables are consid-
ered and stored as strings, even when they are assigned numeric values. The shell and some utilities will
convert numeric strings to their values in order to operate on them as required. Linux is a case-sensitive
system, so the shell considers the variable foo to be different from Foo, and both to be different from FOO.

 

$ salutation=Hello
$ echo $salutation
Hello
$ salutation=”Yes Dear”
$ echo $salutation
Yes Dear
$ salutation=7+5
$ echo $salutation
7+5

 

Note how a string must be delimited by quote marks if it contains spaces. In addition, there can’t be any spaces on either side of the equals sign.

 

$ read salutation
Wie geht’s?
$ echo $salutation
Wie geht’s?

 

The behavior of variables such as $foo inside quotes depends on the type of quotes you use. If you
enclose a $ variable expression in double quotes, then it’s replaced with its value when the line is exe-
cuted. If you enclose it in single quotes, then no substitution takes place. You can also remove the special
meaning of the $ symbol by prefacing it with a /.

 

#!/bin/sh
myvar=”Hi there”
echo $myvar
echo “$myvar”
echo ‘$myvar’
echo /$myvar
echo Enter some text
read myvar
echo ‘$myvar’ now equals $myvar
exit 0

Enrironment Varaible

$HOME
$PATH
$PS1
$PS2

$IFS
$0
$#
$$

 

Parameter Variable

$1,$2,$3

 

Conditions

The test and [ commond

In practice, most scripts make extensive use of the [ or test command, the shell’s Boolean check

 

if test -f fred.c
then
...
fi

 

if [ -f fred.c ]
then
...
fi

 

Note that you must put spaces between the [ braces and the condition being checked. You can remember this by remembering that [ is just the same as writing test, and you would always leave a space after the test command.
If you prefer putting then on the same line as if, you must add a semicolon to separate the test from the then:
if [ -f fred.c ]; then
...
fi

The condition types that you can use with the test command fall into three types: string comparison, arithmetic comparison, and file conditionals.

 

String Comparison Result
string1 = string2 True if the strings are equal
string1 != string2 True if the strings are not equal
-n string True if the string is not null
-z string True if the string is null (an empty string)
Arithmetic Comparison Result
expression1 -eq expression2 True if the expressions are equal
expression1 -ne expression2 True if the expressions are not equal
expression1 -gt expression2 True if expression1 is greater than expression2
expression1 -ge expression2 True if expression1 is greater than or equal to
expression2
expression1 -lt expression2 True if expression1 is less than expression2
expression1 -le expression2 True if expression1 is less than or equal to
expression2
! expression True if the expression is false, and vice versa
File Conditional Result
-d file True if the file is a directory
-e file True if the file exists. Note that historically the -e option
       has not been portable, so -f is usually used.
-f file True if the file is a regular file
-g file True if set-group-id is set on file
-r file True if the file is readable
-s file True if the file has nonzero size
-u file True if set-user-id is set on file
-w file True if the file is writable
-x file True if the file is executable

 

Condition structures

if condition
then
statements
else
statements
fi

 

elif

If you want the echo command to delete the trailing new line, the most portable option is to use the printf command (see the printf section later in this chapter), rather than the echo command. Some shells use echo –e, but that’s not supported on all systems. bash allows echo -n to suppress the new line, so if you are confident your script needs to work only on bash, we suggest using that syntax.

 

for variable in values
do
statements
done

 

What would happen if you changed the first line from for foo in bar fud 43 to for foo in “bar fud 43”? Remember that adding the quotes tells the shell to consider everything between them as a single string. This is one way of getting spaces to be stored in a variable.

 

While

 

while condition do
statements
done

 

#!/bin/sh
echo “Enter password”
read trythis
while [ “$trythis” != “secret” ]; do
echo “Sorry, try again”
read trythis
done
exit 0

 

until

 

until condition
do
statements
done

 

In general, if a loop should always execute at least once, use a while loop; if it may not need to execute at all, use an until loop.

 

case

 

case variable in
pattern [ | pattern] ...) statements;;
pattern [ | pattern] ...) statements;;
...
esac

 

Notice that each pattern line is terminated with double semicolons (;;). You can put multiple state-
ments between each pattern and the next, so a double semicolon is needed to mark where one statement
ends and the next pattern begins.

 

#!/bin/sh
echo “Is it morning? Please answer yes or no”
read timeofday
case “$timeofday” in
yes) echo “Good Morning”;;
no ) echo “Good Afternoon”;;
y ) echo “Good Morning”;;
n ) echo “Good Afternoon”;;
* ) echo “Sorry, answer not recognized”;;
esac
exit 0

It doesn’t look for a best match, just the first match. The default condition often turns out to be the impossible condition, so using * can help in debugging scripts.

 

#!/bin/sh
echo “Is it morning? Please answer yes or no”
read timeofday
case “$timeofday” in
yes | y | Yes | YES ) echo “Good Morning”;;
n* | N* ) echo “Good Afternoon”;;
* ) echo “Sorry, answer not recognized”;;
esac
exit 0

 

remember using " | " as or operation

 

#!/bin/sh
echo “Is it morning? Please answer yes or no”
read timeofday
case “$timeofday” in
yes | y | Yes | YES )
echo “Good Morning”
echo “Up bright and early this morning”
;;
[nN]*)
echo “Good Afternoon”
;;
*)
echo “Sorry, answer not recognized”
echo “Please answer yes or no”
exit 1
;;
esac
exit 0

 

You must be careful to put the most explicit matches first and the most general match last. This is important
because case executes the first match it finds, not the best match. If you put the *) first, it would always be matched, regardless of what was input.

Lists

 

The AND List

 

The AND list construct enables you to execute a series of commands, executing the next command only if all the previous commands have succeeded. The syntax is

 

statement1 && statement2 && statement3 && ...

 

#!/bin/sh
touch file_one
rm -f file_two
if [ -f file_one ] && echo “hello” && [ -f file_two ] && echo “ there”
then
echo “in if”
else
echo “in else”
fi
exit 0

 

The OR list

 

The OR list construct enables us to execute a series of commands until one succeeds, and then not execute any more. The syntax is as follows:

 

statement1 || statement2 || statement3 || ...

 

#!/bin/sh
rm -f file_one
if [ -f file_one ] || echo “hello” || echo “ there”
then
echo “in if”
else
echo “in else”
fi
exit 0

 

Functions

 

To define a shell function, simply write its name followed by empty parentheses and enclose the statements in braces:

 

function_name () {
     statements
}

 

#!/bin/sh
foo() {
echo “Function foo is executing”
}
echo “script starting”
foo
echo “script ended”
exit 0

 

There is no foward declaration in shell, so defind the function before you use it

 

Local variable and global variable

 

#!/bin/sh
sample_text=”global variable”
foo() {
local sample_text=”local variable”
echo “Function foo is executing”
echo $sample_text
}
echo “script starting”
echo $sample_text
foo
echo “script ended”
echo $sample_text
exit 0

Return a value

#!/bin/sh

 

yes_or_no() {
echo “Is your name $* ?”
while true
do
echo -n “Enter yes or no: “
read x
case “$x” in
y | yes ) return 0;;
n | no ) return 1;;
* )
echo “Answer yes or no”
esac
done
}

 

echo “Original parameters are $*“
if yes_or_no “$1”
then
echo “Hi $1, nice name”
else
echo “Never mind”
fi
exit 0

 

Commonds

 

break

 

We use break to escape from for while and until

 

#!/bin/sh
rm -rf fred*
echo > fred1
echo > fred2
mkdir fred3
echo > fred4
for file in fred*
do
if [ -d “$file” ]; then
break;

fi
done
echo first directory starting fred was $file
rm -rf fred*
exit 0

 

:

 

The colon command is a null command. It’s occasionally useful to simplify the logic of conditions, being an alias for true. Since it’s built-in, : runs faster than true, though its output is also much less readable.

 

#!/bin/sh
rm -f fred
if [ -f fred ]; then
:
else
echo file fred did not exist
fi
exit

 

continue

 

Just like the continue in C

 

#!/bin/sh
rm -rf fred*
echo > fred1
echo > fred2
mkdir fred3
echo > fred4

 

for file in fred*
do
if [ -d “$file” ]; then
echo “skipping directory $file”
continue
fi
echo file is $file
done
rm -rf fred*
exit 0

 

for x in 1 2 3
do
echo before $x
continue 1
echo after $x
done

 

The (dot) commond

.

 

excute the commond in the current sheel

. ./shell_script

 

echo

 

eval

 

foo=10
x=foo
y=’$’$x
echo $y

 

gives $foo


but

 

foo=10
x=foo
eval y=’$’$x
echo $y

 

gives 10

 

exec

 

exit n

 

The exit command causes the script to exit with exit code n

 

export

 

#!/bin/sh
echo “$foo”
echo “$bar”

 

#!/bin/sh
foo=”The first meta-syntactic variable”
export bar=”The second meta-syntactic variable”
export2

 

The commands set -a or set -allexport will export all variables thereafter.

 

expr

x=$(expr $x + 1)

 

Expression Evaluation Description
expr1 | expr2 expr1 if expr1 is nonzero, otherwise expr2
expr1 & expr2 Zero if either expression is zero, otherwise expr1
expr1 = expr2 Equal
expr1 > expr2 Greater than
expr1 >= expr2 Greater than or equal to
expr1 < expr2 Less than
expr1 <= expr2 Less than or equal to
expr1 != expr2 Not equal
expr1 + expr2 Addition
expr1 - expr2 Subtraction
expr1 * expr2 Multiplication
expr1 / expr2 Integer division
expr1 % expr2 Integer modulo

 

printf

just like the one in C/C++

 

printf “format string“ parameter1 parameter2 ...

 

Escape Sequence Description
/“ Double quote
// Backslash character
/a Alert (ring the bell or beep)
/b Backspace character
/c Suppress further output
/f Form feed character
/n Newline character
/r Carriage return
/t Tab character
/v Vertical tab character
/ooo The single character with octal value ooo
/xHH The single character with the hexadecimal value HH

 

return

 

set

 

#!/bin/sh
echo the date is $(date)
set $(date)
echo The month is $2
exit 0

 

shift

 

#!/bin/sh
while [ “$1” != “” ]; do
echo “$1”
shift
done
exit 0

 

trap

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值