Shell编程入门总结(二)
来源:互联网 发布:手机qq皮肤制作软件 编辑:程序博客网 时间:2024/05/17 01:09
本文的主要内容:
1、流程控制:while/until 循环
2、流程控制:case 分支
3、流程控制:for 循环
4、位置参数
一、流程控制:while/until 循环
1.while,当遇到一个非零退出状态的时候while 退出循环- while语法:while commands; do commands; done
- 例如(循环输出1-5):
#!/bin/bash# while-count: display a series of numberscount=1while [ $count -le 5 ]; do echo $count count=$((count + 1))doneecho "Finished."
2.跳出循环
- break 命令立即终止一个循环, 且程序继续执行循环之后的语句。continue 命令导致程序跳过循环中剩余的语句,且程序继续执行 下一次循环
- 菜单例子:
#!/bin/bash# while-menu2: a menu driven system information programDELAY=3 # Number of seconds to display resultswhile true; do clear cat <<- _EOF_ Please Select: 1. Display System Information 2. Display Disk Space 3. Display Home Space Utilization 0. Quit _EOF_ read -p "Enter selection [0-3] > " if [[ $REPLY =~ ^[0-3]$ ]]; then if [[ $REPLY == 1 ]]; then echo "Hostname: $HOSTNAME" uptime sleep $DELAY continue fi if [[ $REPLY == 2 ]]; then df -h sleep $DELAY continue fi if [[ $REPLY == 3 ]]; then if [[ $(id -u) -eq 0 ]]; then echo "Home Space Utilization (All Users)" du -sh /home/* else echo "Home Space Utilization ($USER)" du -sh $HOME fi sleep $DELAY continue fi if [[ $REPLY == 0 ]]; then break fi else echo "Invalid entry." sleep $DELAY fidoneecho "Program terminated."
3.until,当遇到一个0退出状态的时候until退出循环
- 例如(循环输出1-5):
#!/bin/bash# until-count: display a series of numberscount=1until [ $count -gt 5 ]; do echo $count count=$((count + 1))doneecho "Finished."
4.使用循环读取文件(其中文件distros.txt中的每一行包含三个字段:distro version release)
- 重定向文件到循环中
#!/bin/bash# while-read: read lines from a filewhile read distro version release; do printf "Distro: %s\tVersion: %s\tReleased: %s\n" \ $distro \ $version \ $releasedone < distros.txt
- 从标准输入管道到循环中
#!/bin/bash# while-read2: read lines from a filesort -k 1,1 -k 2n distros.txt | while read distro version release; do printf "Distro: %s\tVersion: %s\tReleased: %s\n" \ $distro \ $version \ $releasedone
二、流程控制:case 分支
1.case语句
- Bash 的多选复合命令称为 case,其语法规则如下:
case word in[pattern [| pattern]...) commands ;;]...esac
- 使用case的菜单
#!/bin/bash# case-menu: a menu driven system information programclearecho "Please Select:1. Display System Information2. Display Disk Space3. Display Home Space Utilization0. Quit"read -p "Enter selection [0-3] > "case $REPLY in 0) echo "Program terminated." exit ;; 1) echo "Hostname: $HOSTNAME" uptime ;; 2) df -h ;; 3) if [[ $(id -u) -eq 0 ]]; then echo "Home Space Utilization (All Users)" du -sh /home/* else echo "Home Space Utilization ($USER)" du -sh $HOME fi ;; *) echo "Invalid entry" >&2 exit 1 ;;esac
2.模式
- case 语句使用的模式和路径展开中使用的相同。模式以一个 “)” 为终止符。
- 常用的有效模式:
a):若单词为 “a”,则匹配[[:alpha:]]):若单词是一个字母字符,则匹配???):若单词只有3个字符,则匹配*.txt):若单词以 “.txt” 字符结尾,则匹配*):匹配任意单词。可将此模式做为 case 命令的最后一个模式,以捕捉到任何可能的无效值。
- 模式例子:
#!/bin/bashread -p "enter word > "case $REPLY in [[:alpha:]]) echo "is a single alphabetic character." ;; [ABC][0-9]) echo "is A, B, or C followed by a digit." ;; ???) echo "is three characters long." ;; *.txt) echo "is a word ending in '.txt'" ;; *) echo "is something else." ;;esac
- 还可以使用竖线字符作为分隔符,把多个模式结合起来形成一个 “或”条件模式,如" q|Q) "可匹配大写或小写的'q'
3.匹配多个测试条件以执行多个动作
- 添加“;;&” 的语法允许 case 语句继续执行下一条测试,而不是简单地终止运行
- 例子:
#!/bin/bash# case4-2: test a characterread -n 1 -p "Type a character > "echocase $REPLY in [[:upper:]]) echo "'$REPLY' is upper case." ;;& [[:lower:]]) echo "'$REPLY' is lower case." ;;& [[:alpha:]]) echo "'$REPLY' is alphabetic." ;;& [[:digit:]]) echo "'$REPLY' is a digit." ;;& [[:graph:]]) echo "'$REPLY' is a visible character." ;;& [[:punct:]]) echo "'$REPLY' is a punctuation symbol." ;;& [[:space:]]) echo "'$REPLY' is a whitespace character." ;;& [[:xdigit:]]) echo "'$REPLY' is a hexadecimal digit." ;;&esac
当输入'a'时能匹配[[:lower:]]、[[:alpha:]]、[[:graph:]]和[[:xdigit:]]并显示相应输出
三、流程控制:for 循环
1.for: 传统 shell 格式
for variable [in words]; do
commands
done
- 例如:
$ for i in A B C D; do echo $i; done
A
B
C
D
- 或者通过花括号展开:
$ for i in {A..D}; do echo $i; done
A
B
C
D
- 或者路径名展开:
$ for i in distros*.txt; do echo $i; done
distros-by-date.txt
distros-dates.txt
distros-key-names.txt
distros-names.txt
distros.txt
- 或者命令替换:
#!/bin/bash# longest-word : find longest string in a filewhile [[ -n $1 ]]; do if [[ -r $1 ]]; then max_word= max_len=0 for i in $(strings $1); do len=$(echo $i | wc -c) if (( len > max_len )); then max_len=$len max_word=$i fi done echo "$1: '$max_word' ($max_len characters)" fi shiftdone
2.for: C 语言格式
for (( expression1; expression2; expression3 )); do
commands
done
- 在行为方面,这相当于以下构造形式:
(( expression1 ))
while (( expression2 )); do
commands
(( expression3 ))
done
- 例如输出0-4:
#!/bin/bash# simple_counter : demo of C style for commandfor (( i=0; i<5; i=i+1 )); do echo $idone
四、位置参数
1.访问命令行
- shell 提供了一个称为位置参数的变量集合,这个集合包含了命令行中所有独立的单词。这些变量按照从0到9给予命名
- 例如
#!/bin/bash# posit-param: script to view command line parametersecho "\$0 = $0\$1 = $1\$2 = $2"当执行$ posit-param时运行结果:
$0 = /home/me/bin/posit-param$1 =$2 =
- 其中位置参数 $0 为执行程序的路径名
- 访问大于9的参数时,用花括号把该数字括起来即可。 例如 ${10}, ${666} ...
2.确定参数个数
- shell 提供了一个名为 $#的变量,可以得到命令行参数个数
- 例如:
#!/bin/bash# posit-param: script to view command line parametersecho "Number of arguments: $#\$0 = $0\$1 = $1\$2 = $2"当执行$ posit-param a b 时运行结果为
Number of arguments: 2$0 = /home/me/bin/posit-param$1 = a$2 = b
- 执行一次 shift 命令, 就会使所有的位置参数“向下移动一个位置”
- 例如:
#!/bin/bash# posit-param2: script to display all argumentscount=1while [[ $# -gt 0 ]]; do echo "Argument $count = $1" count=$((count + 1)) shiftdone当执行$ posit-param2 a b c时运行结果为:
Argument 1 = aArgument 2 = bArgument 3 = c
- 每次 shift 命令执行的时候,变量 $2 的值会移动到变量 $1 中,变量 $3 的值会移动到变量 $2 中,依次类推。 变量 $# 的值也会相应的减1。
4.简单应用
- 显示一个具体文件的文件类型(由 file 命令确定)和文件状态(来自 stat 命令)
#!/bin/bash# file_info: simple file information programPROGNAME=$(basename $0)if [[ -e $1 ]]; then echo -e "\nFile Type:" file $1 echo -e "\nFile Status:" stat $1else echo "$PROGNAME: usage: $PROGNAME file" >&2 exit 1fi
其中basename 命令清除 一个路径名的开头部分,只留下一个文件的基本名称
5.Shell 函数中使用位置参数
- 例如:
file_info () { # file_info: function to display file information if [[ -e $1 ]]; then echo -e "\nFile Type:" file $1 echo -e "\nFile Status:" stat $1 else echo "$FUNCNAME: usage: $FUNCNAME file" >&2 return 1 fi}
6.处理集体位置参数
- shell 提供了两种特殊的参数:
$*:展开成一个从1开始的位置参数列表。当它被用双引号引起来的时候,展开成一个由双引号引起来 的字符串,包含了所有的位置参数,每个位置参数由 shell 变量 IFS 的第一个字符(默认为一个空格)分隔开。
$@:展开成一个从1开始的位置参数列表。当它被用双引号引起来的时候, 它把每一个位置参数展开成一个由双引号引起来的分开的字符串。
- 例如:
#!/bin/bash# posit-params3 : script to demonstrate $* and $@print_params () { echo "\$1 = $1" echo "\$2 = $2" echo "\$3 = $3" echo "\$4 = $4"}pass_params () { echo -e "\n" '$* :'; print_params $* echo -e "\n" '"$*" :'; print_params "$*" echo -e "\n" '$@ :'; print_params $@ echo -e "\n" '"$@" :'; print_params "$@"}pass_params "word" "words with spaces"
运行结果为:
$ posit-param3$* :$1 = word$2 = words$3 = with$4 = spaces"$*" :$1 = word words with spaces$2 =$3 =$4 =$@ :$1 = word$2 = words$3 = with$4 = spaces"$@" :$1 = word$2 = words with spaces$3 =$4 =
- 其中通过参数,$* 和 $@ 两个都产生了一个有四个词的结果:
"$*" 产生了一个串:"word words with spaces""$@" 产生了两个串:"word" "words with spaces"
- 目前看来“$@” 在大多数情况下是最有用的方法,因为它保留了每一个位置参数的完整性。
7.实例:输出一个包含系统信息的网页
#!/bin/bash# sys_info_page: program to output a system information pagePROGNAME=$(basename $0)TITLE="System Information Report For $HOSTNAME"CURRENT_TIME=$(date +"%x %r %Z")TIMESTAMP="Generated $CURRENT_TIME, by $USER"report_uptime () { cat <<- _EOF_ <H2>System Uptime</H2> <PRE>$(uptime)</PRE> _EOF_ return}report_disk_space () { cat <<- _EOF_ <H2>Disk Space Utilization</H2> <PRE>$(df -h)</PRE> _EOF_ return}report_home_space () { if [[ $(id -u) -eq 0 ]]; then cat <<- _EOF_ <H2>Home Space Utilization (All Users)</H2> <PRE>$(du -sh /home/*)</PRE> _EOF_ else cat <<- _EOF_ <H2>Home Space Utilization ($USER)</H2> <PRE>$(du -sh $HOME)</PRE> _EOF_ fi return}usage () { echo "$PROGNAME: usage: $PROGNAME [-f file | -i]" return}write_html_page () { cat <<- _EOF_ <HTML> <HEAD> <TITLE>$TITLE</TITLE> </HEAD> <BODY> <H1>$TITLE</H1> <P>$TIMESTAMP</P> $(report_uptime) $(report_disk_space) $(report_home_space) </BODY> </HTML> _EOF_ return}# process command line optionsinteractive=filename=while [[ -n $1 ]]; do case $1 in -f | --file) shift filename=$1 ;; -i | --interactive) interactive=1 ;; -h | --help) usage exit ;; *) usage >&2 exit 1 ;; esac shiftdone# interactive modeif [[ -n $interactive ]]; then while true; do read -p "Enter name of output file: " filename if [[ -e $filename ]]; then read -p "'$filename' exists. Overwrite? [y/n/q] > " case $REPLY in Y|y) break ;; Q|q) echo "Program terminated." exit ;; *) continue ;; esac fi donefi# output html pageif [[ -n $filename ]]; then if touch $filename && [[ -f $filename ]]; then write_html_page > $filename else echo "$PROGNAME: Cannot write file '$filename'" >&2 exit 1 fielse write_html_pagefi
参考:《The Linux Command Line》
1 0
- Shell编程入门总结(二)
- shell编程入门(二)
- shell编程入门总结
- Powershell快速入门(二) Shell编程
- Shell编程入门总结(一)
- Shell编程入门总结(三)
- SHELL编程入门(二)---SHELL循环与条件
- shell编程(二)
- shell编程(二)
- shell编程(二)
- shell编程---(二)
- Linux开发基础:Shell编程入门(二)
- Linux学习总结(二)——Shell编程
- Shell编程入门总结(编辑器Vim篇)
- Shell编程入门总结(正则表达式篇)
- Shell编程入门总结(语法篇)
- Shell编程入门总结(编辑器Vim篇)
- Shell脚本入门(二) - Hello Shell
- shell脚本
- 文件系统操作与磁盘管理
- 关于kmp的简单解说
- windows常用快捷键
- 【深度优先搜索】种族部落
- Shell编程入门总结(二)
- 求两点之间的距离
- hiho 57 高斯消元 二
- 程序员的自我修养第三章笔记
- spark DataFrame用法
- 找到环状序列的最小字典表示
- HDU 2018 母牛的故事(递推)
- HDU-4405 Aeroplane chess (概率DP)
- Java mail API学习