Linux命令行和Shell脚本编程(二)

一、Linux命令行

Linux命令行和Shell脚本编程(一)

二、Shell脚本编程

2.3 循环语句for

#格式1
for var in list
do
commands
done
#格式2
for (( variable assignment ; condition ; iteration process ))
#示例
for test in Alabama Alaska Arizona Arkansas California Colorado
for test in I don't know if this'll work    #error,I@dont know if thisll@work
for test in I don\'t know if "this'll" work
"
for test in Nevada New Hampshire New Mexico New York North Carolina    #error
for test in Nevada "New Hampshire" "New Mexico" "New York"

list="Alabama Alaska Arizona Arkansas Colorado"
list=$list" Connecticut"
for state in $list

for state in $(cat $file)
IFS=$'\n'
for state in $(cat $file)

for file in /home/rich/test/*

内部字段分隔符(IFS):

IFS环境变量定义了bash shell用作字段分隔符的一系列字符 默认是空格、制表符和换行符 

可以在shell脚本中临时更改IFS环境变量的值来限制被bash shell当作字段分隔符的字符 

2.4 循环语句while

#格式1
while test command
do
other commands
done
#格式2
while [ condition ]
do
other commands
done

 while命令每次迭代时检查测试条件,只要测试条件成立, while命令就会不停地循环执行定义好的命令 

2.5 循环语句until

#格式1
until test command
do
other commands
done
#格式2
until [ condition ]
do
other commands
done

 until命令每次迭代时检查测试条件,只要测试条件不成立, until命令就会不停地循环执行定义好的命令

2.6 循环控制break,continue

break命令:退出循环
continue命令 :提前中止某次循环,但不会终止循环  

2.7 处理用户输入/输出

命令行参数:

Shell提供位置参数在脚本中使用

$0是程序名, $1是第一个参数, $2是第二个参数,依次类推,直到第九个参数$9 

如果有超过9个参数,在使用时用花括号,如${10} 

特殊参数变量:

$#:表示脚本运行时命令行参数的个数,不包含文件名

${!#}:表示最后一个参数的值

$*:表示将命令行上所有参数当作一个字符串保存

$@:表示将命令行上提供的每一个参数当作独立字符串来保存

移动变量:

shift命令表示将所有参数向左移动一个位置

适用于在不知道用户传多少参数时,只操作第一个参数,然后移动参数,继续操作第一个参数 

shift n:表示将所有参数向左移动n个位置
接受用户输入:

read var
read -p "description" var
read –t 5 var #设置超时时间
read –n1 var #表示变量名只接受一个字符
read –s var #隐藏方式读取 

处理输出:

Linux用文件描述符(file descriptor)来标识每个文件对象。文件描述符是一个非负整数,可以唯一标识会话中打开的文件。每个进程一次最多可以有九个文件描述符。出于特殊目的, bash shell保留了前三个文件描述符(0、 1和2)

重定向错误:

如果只重定向错误消息,将文件描述符值放在重定向符号前,且不能出现空格

ls -al badfile 2> test4 #重定向错误
ls -al test test2 badtest 2> test6 1> test7 #重定向错误和正常输出
ls -al test test2 badtest &> test7 #重定向错误和正常输出到一个文件

command >&2 #将命令输出指定到错误输出
echo "and this should be stored in the file" >&2

exec 1> testout #永久重定向标准输出到testout文件
exec 2> testerror #永久重定向标准错误到testerror文件
exec 0< testfile #永久重定向testfile为标准输入
exec 3> test13out #创建自己的输出文件描述符
echo "and this should be stored in the file" >&3
exec 1>&3 #将标准输出重定向到文件描述符3

exec 6<&0 #将标准输入重定向到文件描述符6,相当于是保存下标准输入重定向,之后再赋值回去
exec 0< testfile
exec 0<&6
exec 6>&- #关闭文件描述符

ls -al > /dev/null #阻止命令输出
cat /dev/null > testfile

三、高级Shell脚本编程

3.1 函数

#格式1:
function name {
commands
}
#格式2:
name() {
commands
}

注意:花括号之前要有空格

#向函数传递参数
fun1 $val1 $val2

#传递命令行参数
function badfunc1 {
echo $[ $1 * $2 ]
}
value=$(badfunc1)    #error
value=$(func7 $1 $2)

return命令来退出函数并返回特定的退出状态码,保存在$?
echo可以返回函数的返回值
由于函数使用特殊参数环境变量作为自己的参数值,因此它无法直接获取脚本在命令行中的参数值。
 全局变量和局部变量:

Shell脚本中定义的变量都是全局变量,包括在函数中定义的变量,即函数内定义的变量,函数外也可以访问并赋值

local  变量名:即使与全局变量同名,函数内部会使用局部变量

函数的作用域:
shell函数仅在定义它的shell会话内有效,而shell会创建一个新的shell并在其中运行脚本

#!/bin/bash
./myfuncs
result=$(addem 10 15)    #error
. ./myfuncs    #点操作符,是source的别名

3.2 grep

选项 描述
-c

只输出匹配到的行数

-e

指定多个匹配模式

-E

支持扩展正则表达式

-i

忽略大小写

-n

标出行号

-o

只输出匹配到的部分

-r

递归查找

-v

输入不符合条件的行 

#示例
grep [option] pattern file
grep -c "hello" file
grep -rn "hello"
grep -i "Hello" file
grep -v "hello" file
grep -o "hello" file
grep -e "hello" -e "cat" file
grep -n "hello" file*
grep -n "^hello" file
grep -n "hello$" file
grep -n "hello*" file
grep -n "hello." file
grep -n "hello[1,2]" file
grep -n "hello[^1,2]" file

3.3 awk

#awk格式
awk options command file

 

#awk命令示例
echo "test" | awk '{print "Hello World!"}'    #Hello World!
awk '{print $1}' data.txt#$0表示整行,$1表示第一列,$2表示第二列,$n表示第n列
awk -F: '{print $1}' /etc/passwd
echo "My name is Rich" | awk '{$4="Christine"; print $0}'
awk -F: -f script.gawk /etc/passwd    #{print $1, $2}

awk options 'BEGIN{} // {command1;command2} END{}' file    #//是正则表达式

awk 'BEGIN {print "Hello World!"}; {print $1}' data.txt
awk 'BEGIN {print "Hello World!"}; {print $1}; END {print "End of File"}' data.txt
awk 'BEGIN{FS=","} {print $1,$2,$3}' data1    #data1文件以,作为分隔符
awk 'BEGIN{FS=","; OFS="-"} {print $1,$2,$3}' data1    #以,分隔符读取,以-分隔符输出

3.4 sed

#sed格式
sed options command file

#替换
echo "This is a test" | sed 's/test/big test/'
sed 's/dog/cat/' data1.txt
sed -e 's/brown/green/; s/dog/cat/' data1.txt
sed -f script1.sed data1.txt
sed 's/dog/cat/2' data1.txt
sed 's/dog/cat/g' data1.txt
sed -n 's/dog/cat/p' data1.txt #只输出被替换的行,-n选项禁止sed编辑器输出
sed 's/test/trial/w test.txt' data5.txt
sed 's!/bin/bash!/bin/csh!' /etc/passwd
sed '2s/dog/cat/' data1.txt
sed '2,3s/dog/cat/' data1.txt
sed '2,$s/dog/cat/' data1.txt #从第2行到最后一行
sed '/Lewis/s/bash/csh/' /etc/passwd
#删除
sed 'd' data1.txt   
sed '3d' data1.txt
sed '2,3d' data1.txt 
sed '3,$d' data1.txt
sed '/number 1/d' data1.txt #将含有number 1的行删除
#插入/附加
echo "Test Line 2" | sed 'i\Test Line 1' #插入文本出现在流文本前面
echo "Test Line 2" | sed 'a\Test Line 1' #附加文本出现在流文本后面
sed '3i\This is an inserted line.' data6.txt #在第三行插入
sed '3a\This is an appended line.' data6.txt #在第四行插入
sed '$a\This is an appended line.' data6.txt
#修改
sed '3c\This is a changed line of text.' data6.txt
sed '2,3c\This is a changed line of text.' data6.txt
sed '/number 3/c\This is a changed line of text.' data6.txt
#写入文件
sed '1,2w test.txt' data6.txt
sed -n '/Lewis/w Lewis.txt' /etc/passwd

3.5 正则表达式

基础正则表达式:
^ :只匹配行首
$ :只匹配行尾
.  :匹配除换行符之外的任意单个字符
* :匹配0次或多次 
[ch] :只匹配字符组中出现的字符,支持[0-9] ,[c-h] 
[^ch] :匹配除字符组中字符的其他字符

扩展正则表达式:

? :匹配0次或1次
+ :匹配1次或多次
{m}:匹配m次
{m, n}:匹配m到n次
| :或,匹配多个模式
() :括号内的字符串被认为是一个整体
 

#正则表达式之grep
grep -E "hello?" file
grep -E "hello+" file
grep -E "hello{2}" file
grep -E "hello{2,3}" file
grep -E "hello?|hi" file
grep -E "he(llo)?" file

#正则表达式之sed
echo "The books are expensive" | sed -n '/book/p'
echo "Books are great" | sed -n '/^Book/p'
echo "This ^ is a test" | sed -n '/s ^/p'
echo "This is a good book" | sed -n '/book$/p'
sed -n '/^this is a test$/p' data4
sed '/^$/d' data5
sed -n '/.at/p' data6 #可以匹配cat, at
sed -n '/[ch]at/p' data6
sed -n '/[^ch]at/p' data6
sed -n '/^[0-9][0-9][0-9]$/p' data8
echo "abc" | sed -n '/[[:alpha:]]/p'
echo "ik" | sed -n '/ie*k/p'
echo "ieeek" | sed -n '/ie*k/p'
echo "bat" | sed -n '/b[ae]*t/p'
echo "bet" | sed -n '/b[ae]*t/p'

#正则表达式之awk
echo "bet" | awk '/be?t/{print $0}'
echo "beet" | awk '/be?t/{print $0}' #no output
echo "bat" | awk '/b[ae]?t/{print $0}'
echo "bet" | awk '/be+t/{print $0}'
echo "bt" | awk '/be+t/{print $0}' #no output
echo "bat" | awk '/b[ae]+t/{print $0}'
echo "bet" | awk '/be{1}t/{print $0}'
echo "beet" | awk '/be{1,2}t/{print $0}'
echo "bat" | awk '/b[ae]{1,2}t/{print $0}'
echo "The cat is asleep" | awk '/cat|dog/{print $0}'
echo "He has a hat." | awk '/[ch]at|dog/{print $0}'
echo "Saturday" | awk '/Sat(urday)?/{print $0}'

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章