Shell编程笔记

文章详细介绍了Linuxshell脚本中处理命令行参数的方法,包括特殊变量如$0,$#,$*,$@等的用法,以及如何通过getopts处理命令选项。此外,还讲解了使用read命令获取用户输入,以及文件I/O操作,如重定向和临时文件的创建。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

处理用户输入

命令行参数

读取参数

./test 10 30

10和30即命令行参数

$0保存程序名(即./test),$1是第一个参数,$2是第二个......${10}第十个参数,两位数以上则用大括号括起来

各参数通过空格区分,如果参数本身含有空格,则添加引号

./test "Rich Blum"

 读取脚本名

$0存在的问题:保存的是程序名包括路径

basename命令

echo $(basename $0)

若程序名为/home/xxx/test.sh,则输出test.sh

其实,basename仅仅是一个字符串截取工具,截取最后一部分即是文件名,对应的有dirname命令,截取目录名(在本例中为/home/xxx)

特殊参数变量

$#参数

记录了命令行参数个数

虽然$#可以当作普通变量使用,但是注意$f符号嵌套使用内部$要用!代替:

echo ${$#} #试图输出最后一个参数,但是是错误写法
#正确写法:
echo ${!#}

$*和$@参数

二者都是获取全部命令行参数,但是前者将所有参数视为一个整体(即当成一个长字符串),后者相当于参数的数组

移动参数

shift命令

通过shift命令可以将命令行参数依次左移,有下例子:

count=1
while [ -n "$1" ] ; do
    echo "Parameter #$count:"$1
    count=$[$count+1]
    shift
done

./test.sh a b c d

输出如下:
Parameter #1:a
Parameter #2:b
Parameter #3:c
Parameter #4:d

shift参数也可以指定左移位数:

shift 2 #左移两位

 处理命令选项

使用getopts命令

使用格式:

getopts optstring variable

如果选项字母有参数值,就在后面加一个冒号,参数保存在variable(用户自定义)中,参数值保存在OPTARG中;要去掉错误消息的话也是在optstring前加冒号;OPTIND记录了正在处理的参数位置。

有如下例子:

while getopts :ab:c opt ; do
  case "$opt" in
    a) echo "Found the -a option" ;;
    b) echo "Found the -b option,with value : $OPTARG" ;;
    c) echo "Found the -c option" ;;
    *) echo "Unknown option:$opt" ;;
  esac
done

./test.sh -a -b test -c -d

输出:
Found the -a option
Found the -b option,with value : test
Found the -c option
Unknown option:?

 注意到:未列出的选项getopts统一记录为?

获取用户输入-read命令

基本读取

-p:指定提示信息

$ read -p "Please input your age:" age

Please input your age: 10

 read将读取到的值存入用户定义的变量中(上例中为age),另外如果不指定变量,则read默认将输入值存入环境变量REPLY

-t:指定超时时间

$ read -t 5 -p "Please input your age:" age

 上例中,read指定超时时间为5秒,超时后read返回非零状态码

-n:后接数字表示接收几个字符后退出

$ read -n1 -p "Do you want do this [Y/N] ?" answer

 用户输入一个字符后read立马返回,不用按回车键

-s:隐藏输入的数据(实际上read是将文字颜色设置为背景颜色)

$ read -s -p "Enter your password:" password

屏幕上不会出现用户输入的字符

 从文件中读取

常见的方法是使用cat加管道符:

cat text | while read line
do
  echo $line
done

text中内容如下:

hello,world
beautiful love
 

注意,text文件中末尾空行必须有,否则有内容的最后一行将无法输出(我也不知道啥原因) 

./test.sh

输出:
hello,world
beautiful love

 文件IO

输入/输出重定向

Linux文件描述符

Linux用文件描述符来标识每个文件对象,每个进程最多可以有九个文件描述符(0~8),bash保留了前三个:

0:STDIN,即标准输入

1:STDOUT,即标准输出

2:STDERR,即标准错误输出

对文件描述符指向的文件,可以通过&来引用:

$ echo "hello,world" > &2

上述指令将echo输出到文件描述符2所指向的文件 

重定向符号(<,>)

<:输入重定向,用指定文件代替标准输入

>:输出重定向,用指定文件代替标准输出。注意:标准错误输出并没有被重定向,依然为屏幕

重定向标准错误输出

只重定向错误输出,使用 2>:

$ ls -al badfile 2> test4

 "2>"的意思是将文件描述符2(也就是STDERR)指向后面的文件

重定向标准输出和错误输出,使用 &>

$ ls -al badfile &> test7

在这种情况中,bash自动赋予错误信息更高的优先级,错误消息显示在文本开头 

在脚本中永久重定向,使用exec命令

exec 1>testout

上述指令将1(也就是STDOUT)指向testout

exec 0< testfile

上述指令将0(也就是标准输入)指向testfile

----

对文件描述符的使用就像使用指针

关闭文件描述符

exec 3> &-

上述指令将3文件描述符关闭

15.6 阻止命令输出

null文件

将输出写入到null文件,null文件将不含任何内容:

$ ls -al > /dev/null

$ cat /dev/null

$

 可以使用null文件作为清空文件的一种手段:

$ cat /dev/null > testfile

$ cat testfile

$

15.7 创建临时文件

Linux使用/temp目录来保存临时文件,启动时自动删除里面的内容。

使用 mktemp 命令

创建本地临时文件

默认情况下,mktemp会在本地目录创建一个临时文件,你只需要指定一个文件名模板就可以了,模板包含任意文件名后跟6个X:

$ mktemp testing.XXXXXX

testing.P1xKkI

$ ls -al testing*
-rw------- 1 root root 0 Feb 25 00:26 testing.P1xKkI

 在脚本中使用时,需要使用mktemp命令返回的文件名:

tempfile=$(mktemp testing.XXXXXX)

在/temp目录创建临时文件

使用-t选项,mktemp命令返回完整路径名,而不仅仅是文件名:

$ mktemp -t testing.XXXXXX
/tmp/testing.5V2lT1

$ ls -al /tmp/testing*
-rw------- 1 root root 0 Feb 25 00:31 /tmp/testing.5V2lT1

 创建临时目录

使用-d选项创建一个临时目录

tempdir=$(mktemp -d tempdir.XXXXXX)
cd $tempdir
tempfile=$(mktemp testing1.XXXXXX)
exec 7>$tempfile
echo "这是一个临时文件内容" >&7

第16章 控制脚本

16.1 处理信号

常见Linux信号

Linux信号
信号描述
1

SIGHUP

挂起进程
2SIGINT终止进程
3

SIGQUIT

停止进程
9SIGKILL杀死进程
15SIGTERM尽可能终止进程
17SIGSTOP无条件停止进程
18SIGTSTP停止或暂停进程
19SIGCONT继续运行停止的进程

生成信号

1.中断进程

Ctrl+C组合键,生成SIGINT信号,终止进程

2.Ctrl+Z组合键,生成SIGTSTP信号,停止进程,进程仍在内存中保留,并且能恢复继续执行

$ sleep 100
^Z
[1]  + 19832 suspended  sleep 100

方括号是shell分配给进程的唯一的作业号 。

可以使用ps -l查看已停止进程:

$ ps -l
F S   UID   PID  PPID  C PRI  NI ADDR SZ WCHAN  TTY          TIME CMD
4 S     0 13882 13665  0  80   0 - 36763 sigsus pts/4    00:00:00 zsh
0 T     0 19832 13882  0  80   0 - 27014 do_sig pts/4    00:00:00 sleep
0 R     0 20206 13882  0  80   0 - 38332 -      pts/4    00:00:00 ps

 在S状态栏为T的表示已停止

捕获信号

trap commands signals

示例:

trap "echo 'Sorry,I have trapped Ctrl-C'" SIGINT
echo "This is a test script"
count=1
while [ $count -le 10 ] ; do
  echo "Loop #$count"
  sleep 1
  count=$[$count+1]
done
echo "The test script is over"

 $ ./test.sh 
This is a test script
Loop #1
Loop #2
^CSorry,I have trapped Ctrl-C
Loop #3
Loop #4
^CSorry,I have trapped Ctrl-C
Loop #5
Loop #6
^CSorry,I have trapped Ctrl-C
Loop #7
Loop #8
Loop #9
Loop #10
The test script is over

 恢复默认信号行为

trap -- SIGINT

单破折号也可以

16.2 以后台模式运行脚本

在命令后加&符号即可后台启动脚本

如果终端会话退出,该终端会话的所有后台进程也会随之退出

16.3  在非控制台下运行后台脚本

使用nohup命令来阻断发送给进程的SIGHUP信号

因为使用nohup命令后,进程与终端失去联系,进程的STDOUT和STDERR重定向到名为nohup.out的文件中,

16.4 作业控制

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值