bash4----进阶1 内部变量
0、操作符之求最小公约数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | #!/bin/bash ARGS=2 E_BADARGS=65 #args check #--------------------------------------- if [ "$ARGS" - ne $ # ] then echo "Usage: `basename $0` num1 num2 " exit E_BADARGS fi #--------------------------------------- gcd() { divisor=$1 dividend=$2 remainder=1 until [ remainder - eq 0 ] do let "remainder=$dividend%$divisor" dividend=$divisor divisor=$remainder done } gcd $1 $2 echo "the gcd of $1 and $2 is $dividend" exit 0 |
1、内部变量
BASH ----> /bin/bash
$FUNCTION ----> 当前函数的名字
$GROUP ----> 用户所在的组
$HOME ----> /home/username
$MACHTYPE ----> 标识系统的硬件(x86_64-pc-linux-gnu)
*** $OLDPWD ----> 之前的工作目录
$PWD ----> 工作目录
$OSTYPE ----> 操作系统类型
*** $PATH ----> 可执行文件的搜索路径
当给出一个命令时, shell会自动生成一张哈希(hash)表, 并且在这张哈希表中按照path变量中所列出的路径来搜索这个可执行命令. 路径会存储在环境变量中, $PATH变量本身就一个以冒号分隔的目录列表. 通常情况下, 系统都是在/etc/profile和~/.bashrc中存储$PATH的定义.
其中PATH=PATH会恢复以前的值
PPID就是这个进程的父进程的ID
PS1显示之前需要执行的命令
$PS1 主提示符
$PS2 第二提示符默认显示为'>'
$PS3 第三提示符,他在一个select循环中显示
$PS4 第四提示符,当你使用-x选项来调试脚本时,这个提示符会出现在每一行输出的开头,默认显示为+
SHLVL为1, 如果在脚本中那么$SHLVL为2.
1.1$IFS 内部域分隔符
对于for arg in "$var1 var2 var3"
第一次循环,arg=$var1
第二次循环,arg=$var2
。。。。
这里的var1 和var2之间由IFS进行单词分割,如果不想进行单词分割 需要加上“”
所以可以直接写出output_args_one_per_line()函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | #!/bin/bash # $IFS 处理空白与处理其他字符不同. output_args_one_per_line() { for arg do echo "[$arg]" done } echo ; echo "IFS=\" \"" echo "-------" IFS= " " var= " a b c " output_args_one_per_line $var # output_args_one_per_line ` echo " a b c " ` [a] [b] [c] echo ; echo "IFS=:" echo "-----" IFS=: var= ":a::b:c:::" # 与上边一样, 但是用" "替换了":". output_args_one_per_line $var # # [] # [a] # [] # [b] # [c] # [] # [] # [] # 同样的事情也会发生在awk的"FS"域中. # 感谢, Stephane Chazelas. echo exit 0 |
2、$REPLY
当没有参数变量提供给read命令的时候, 这个变量会作为默认变量提供给read命令. 也可以用于select菜单, 但是只提供所选择变量的编号, 而不是变量本身的值。当且仅当没有变量提供给"read"命令时,12 #+ REPLY才保存最后一个"read"命令读入的值.当输入多个值时fruit被传入到了这个新的"read"命令中。
1 2 3 4 5 | #!/bin/bash echo echo -n "what is your favorite vegetable?" read #A echo "Your favorete vegetable is $REPLY" #A<br>echo<br>echo -n "What is your favorite fruit?" <br>read fruit #B<br>echo "Your favorite fruit is $fruit." #B<br>echo "But..."<br>echo "Value of \$REPLY is still $REPLY" #A |
3、$TMOUT
如果$TMOUT环境变量被设置为非零值time的话, 那么经过time秒后, shell提示符将会超时. 这将会导致登出(logout).
9-2.定时输入
知识点:
1、$是本脚本的进程ID
2、kill命令:
kill [信号量] PID
我们可以通过kill -l 来查看信号量有哪些。这里的15是SIGTERM信号终止(区别于9,15是可以被忽略,进程可以用一段时间来正常关闭,一个程序的正常关闭一般需要一段时间来保存进度并释放资源。换句话说,它不是强制停止。)
同理trap commands signals,也可以通过trap -l查找信号量。结果差不多相同(我没有注意比较)
-信号"可使用信号代码或信号名称。kill后可跟多个进程编号,kill会把指定的信号都传递给这些进程。如果省略"-信号"则默认传送SIGTERM(代码15,终止进程)信号给进程。 只要系统产生特定信号,trap就会触发指令。trap 'echo 123' ABRT ; kill -ABRT 代表当前shell进程编号
trap "" HUP INT QUIT KILL #则会屏蔽HUP INT QUIT KILL这几个信号。
3、这个脚本的顺序:先echo "what is your favorite..."
然后执行函数TimerOn和read
如果函数TimerOn等待超过TIMELIMIT则执行TimerOn中的kill,陷入Int14Vector函数,赋值answer=TIMEOUT并执行PrintAnswer。这个里面TimerOn函数已经在后台运行完成了,所以不需要kill
如果函数TimerOn等待不超过TIMELIMIT,read就已经完成,则直接执行PrintAnswer并kill还在后台运行的TimerOn函数用$!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | #!/bin/bash # timed-input.sh # TMOUT=3 在新一些的Bash版本上也能运行的很好. TIMELIMIT=3 # 这个例子中设置的是3秒. 也可以设置为其他的时间值. PrintAnswer() { if [ "$answer" = TIMEOUT ] then echo $answer else # 别和上边的例子弄混了. echo "Your favorite veggie is $answer" kill $! # 不再需要后台运行的TimerOn函数了, kill了吧. # $! 变量是上一个在后台运行的作业的PID. fi } TimerOn() { sleep $TIMELIMIT && kill -s 14 $$ & # 等待3秒, 然后给脚本发送一个信号. } Int14Vector() { answer= "TIMEOUT" PrintAnswer exit 14 } trap Int14Vector 14 # 定时中断(14)会暗中给定时间限制. echo "What is your favorite vegetable " TimerOn read answer PrintAnswer # 无可否认, 这是一个定时输入的复杂实现, #+ 然而"read"命令的"-t"选项可以简化这个任务. # 参考后边的"t-out.sh". # 如果你需要一个真正优雅的写法... #+ 建议你使用C或C++来重写这个应用, #+ 你可以使用合适的函数库, 比如'alarm'和'setitimer'来完成这个任务. exit 0 |
使用stty写的另外一个定时输入:
更多关于stty的详细描述,可以查看这个博文。
命令stty:
stty [option] [setting]...
例如:设置一个擦除字符
stty erase '#' #将backspace(^?)改成了'#'用来退格。
这里的erase是option中的特殊字符设置。
设置分为:control setting.input setting. output setting local setting combination setting characters setting special setting .
另外stty -a是使用用户可读的方式输出设置
stty -g是用stty方式输出(具体用法就是其中一个如下代码)
old_tty_settings=`stty -g` #保存旧的tty在变量中
stty -icanon min 0 time ${timeout}0 #[-]icanon 启用erase、kill、werase 和rprnt 等特殊字符
#min N 和 -icanon 配合使用,设置每次一完整读入的最小字符数为<N>
# time N 和-icanon 配合使用,设置读取超时为N 个十分之一秒(因为是N个十分之一秒,所以后面要加个0,才是对应秒数)
eval read $varname # eval [parameter]:参数说明:参数不限数目,彼此之间用分号分开。
#eval 执行以下两个步骤:
#第一步,执行变量替换,类似与C语言的宏替代;
#第二步,执行替换后的命令串。
#eg:WORD="cat test"; echo WORD
#echo显示cat test 而eval 则把变量替换,然后执行命令。
另外,#表示#
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | #!/bin/bash # timeout.sh # 由Stephane Chazelas所编写, #+ 本书作者做了一些修改. INTERVAL=5 # 超时间隔 timedout_read() { timeout=$1 varname=$2 old_tty_settings=`stty -g` stty -icanon min 0 time ${timeout}0 eval read $varname # 或者仅仅读取$varname变量 stty "$old_tty_settings" # 参考"stty"的man页. } echo ; echo -n "What's your name? Quick! " timedout_read $INTERVAL your_name # 这种方法可能并不是在每种终端类型上都可以正常使用的. # 最大的超时时间依赖于具体的中断类型. #+ (通常是25.5秒). echo if [ ! -z "$your_name" ] # 如果在超时之前名字被键入... then echo "Your name is $your_name." else echo "Timed out." fi echo # 这个脚本的行为可能与脚本"timed-input.sh"的行为有些不同. # 每次按键, 计时器都会重置(译者注: 就是从0开始). exit 0 |
另外 read -t TIMELIMIT varname 也可以定时输入,具体代码不再写出。
如何判断用户ID?
root是$UID=0
另外可以通过命令`id -nu`或`whoami`来判断
"@“和$*的区别:
1、“$*”会将所有的参数看做一个单词
2、@将会把参数看成单独的单词
3、*中的参数表现取决于$IFS的设置。
4、1就丢弃了,$@保存剩下的。
5、当*被双引号引用时候,那么参数会有所不同。(不要用双引号!)
6、当*和$@的行为依赖与bash和sh的版本特性。
$!是运行在后台的一个作业的PID。
$_这个变量保存之前执行的命令的最后一个参数的值。
$?命令,函数,或者是脚本本身的退出状态码
$$脚本自身的进程ID。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix