1、关于$
$是个在shell中有多种使用方式的东东。不经常使用时,也是很容易忘记的一个特殊标识符,记录一下比较常用的几种用法:
- $# : 获得脚本传入参数的个数。
- $? : 获得上面函数或脚本执行之后的返回值(或者叫退出码)。(默认成功执行之后返回0)
- $$ : 获得当前所在脚本的进程ID号。(通常会被作为生成唯一标识的一种手段)
- $! : 获得最后一个后台进程PID。(通常这个可以用来结合后台任务& 来完成一定时间内运行任务的需求:cmd & (sleep 10; kill -9 $! 2>/dev/null))
- $() : 相当于``,也用作命令替换,即先执行括号中的命令,然后返回命令执行的结果。
- $*/$@ : 获取传入脚本的全部参数。但两者在加上引号之后的行为有些差别,后者会把传入参数以空格为分割拆分成多个,前者则还是作为一个整体看待。另外,这个差异也跟脚本的传入参数是否使用了引号有关,具体看一下例子。
-
#a.sh为测试脚本,内容如下 #!/bin/bash echo "The passed in parameters are : $@" echo 'Test $@ : ' for arg in $@ do echo "$arg" done echo 'Test $*: ' for arg in $* do echo "$arg" done echo 'Test "$@" : ' for arg in "$@" do echo "$arg" done echo 'Test "$*": ' for arg in "$*" do echo "$arg" done ## 下面是几种不同调用输出的结果 # use nothing ./a.sh a b c d e The passed in parameters are : a b c d e Test $@ : a b c d e Test $*: a b c d e Test "$@" : a b c d e Test "$*": a b c d e # use " " ./a.sh "a b c d e" The passed in parameters are : a b c d e Test $@ : a b c d e Test $*: a b c d e Test "$@" : a b c d e Test "$*": a b c d e # use ' ' ./a.sh 'a b c d e' The passed in parameters are : a b c d e Test $@ : a b c d e Test $*: a b c d e Test "$@" : a b c d e Test "$*": a b c d e
- 当然,这个种表示还有很多细微的差别不太常用,具体的可以参考这里:http://www.tsnc.edu.cn/default/tsnc_wgrj/doc/abs-3.9.1_cn/html/internalvariables.html#APPREF
-
- ${}: 变量替换
- ${#var}:输出var变量的字符串长度。
-
var=123456789;echo ${#var} 9
-
- ${var#string}/${var##string}/${var%string}/${var%%string}:字符串截取(string中支持Globbing风格的通配符*和?)
-
var1=abcd12345abc6789 pattern1=a*c # *(通配符)匹配a - c之间的任意字符. #从左到右非贪婪式匹配,即匹配到最短的一个就停止,将匹配到的串截掉。 echo '${var1#$pattern1} =' "${var1#$pattern1}" # Output : ${var1#$pattern1} = d12345abc6789 #从左到右贪婪式匹配,即匹配到最长一个才停止,将匹配到的串截掉。 echo '${var1##$pattern1} =' "${var1##$pattern1}" # Output : ${var1##$pattern1} = 6789 pattern2=b*9 # 匹配'b'到'9'之间的任意字符 #从右到左非贪婪式匹配,即匹配到最短的一个就停止,将匹配到的串截掉。 echo '${var1%$pattern2} =' "${var1%$pattern2}" # Output : ${var1%$pattern2} = abcd12345a #从右到左贪婪式匹配,即匹配到最长的一个才停止,将匹配到的串截掉。 echo '${var1%%$pattern2} =' "${var1%%$pattern2}" # Output : ${var1%%$pattern2} = a # 这关于#和%谁截掉左边,谁截掉右边的记法,最简单的就是看看键盘上他们在$符号的左右位置。
#使用这种方式实现的basename的功能 path_name=/home/bozo/ideas/thoughts.for.today t=${path_name##/*/} echo $t #Output: thoughts.for.today
-
-
${var:pos}/${var:pos:len}: 相当于Java中String的subString方法,也是bash中以index方式截取字符串的方法。但这种方式即使下标越界,也不会有任何错误输出。。。
-
var1=abcd12345abc6789 echo ${var1:0} # abcd12345abc6789 echo ${var1:1} # bcd12345abc6789 echo ${var1:0:1} # a
-
-
${var/Pattern/Replacement}: 使用Replacement来替换变量var中第一个匹配Pattern的字符串。
-
var1=abcd-1234-defg;t=${var1/abcd/m*m-};echo $t # Output : m*m--1234-defg # pattern中同样支持*通配符,但同样也是Globbing风格。 var1=abcd-1234-defg;t=${var1/a*d/m*m-};echo $t # Output : m*m-efg
-
- ${var//Pattern/Replacement}:同上,当时多了一个斜杠之后,标识不仅仅替换第一个匹配的字符串,而是全局替换。
-
${var/#Pattern/Replacement}/${var/%Pattern/Replacement}: 这里#和%表示Pattern只匹配字符串的开头或者结尾,功能有点类似于RE中的^和$。
-
v0=abc1234zip1234abc v1=${v0/#abc/ABCDEF} echo "v1 = $v1" # v1 = ABCDEF1234zip1234abc v2=${v0/%abc/ABCDEF} echo "v2 = $v2" # v2 = abc1234zip1234ABCDEF # 123 is neither the prefix nor suffix, so the String will not be replaced. v3=${v0/#123/000} echo "v3 = $v3" # v3 = abc1234zip1234abc v4=${v0/%123/000} echo "v4 = $v4" # v4 = abc1234zip1234abc
-
- ${array[@]}/${array[*]}: 获取数组的全部元素(${array[index]为获取数组中下标为index的那一个元素)。
-
my_array=(a b c d e) echo 'Test ${my_array[@]}' for my in ${my_array[@]} do echo $my done echo 'Test ${my_array[*]}' for my in ${my_array[*]} do echo $my done #The following is the output Test ${my_array[@]} a b c d e Test ${my_array[*]} a b c d e
-
- ${#var}:输出var变量的字符串长度。
- $ : 在正则表达式(RE)中作为行结束符。
2、关于Globbing
Bash本身并不会识别正则表达式,在脚本中,使用RE的是命令和工具。比如sed、awk等工具。Bash仅仅做的是文件名的扩展(当然还有上面提到的关于字符串的替换时使用的通配符),也就是所谓的Globbing。Globbing所使用的通配符最常用的有这3个:*/?/^。
这里面最容易和标准正则表达式产生混淆的就是前面两个通配符。
在RE中,*和?的通配作用主要是基于某个特定的字符的,而在Globbing中,他们的通配作用却可以代表任何字符。具体看个例子:
ls -l -rw-r--r-- 1 sky staff 3269 9 29 15:29 velocity.log -rw-r--r-- 1 sky staff 0 10 6 19:10 velocityab.log -rw-r--r-- 1 sky staff 0 10 6 19:10 velocityyy.log ##Globbing style ls -l *.log -rw-r--r-- 1 sky staff 3269 9 29 15:29 velocity.log -rw-r--r-- 1 sky staff 0 10 6 19:10 velocityab.log -rw-r--r-- 1 sky staff 0 10 6 19:10 velocityyy.log ##RE style, nothing output to the console ls -l|egrep "*.log" egrep: repetition-operator operand invalid ##RE style again ls -l|egrep "velocity*.log" -rw-r--r-- 1 sky staff 3269 9 29 15:29 velocity.log -rw-r--r-- 1 sky staff 0 10 6 19:10 velocityyy.log
从上面的例子可以看出来,RE中,*是不能作为一个独立的“通配单元”存在的,但是Globbing中没有问题,但是需要注意的是,Globbing中*是不会通配以.开头的隐藏文件的。?会有上面类似的解释规则。所以在Globbing中,velocity.???可以被解释为velocity.log,但同样也可以被解释为velocity.123等。
3、关于各种[](包括[[]])
- []用作条件测试:基本上等价于shell内建的test。最常见的就是if/while等后面的判断条件。
- []用作数组元素:直接看例子
-
my_array=(a b c d e); echo "The first element is : ${my_array[0]}" #The first element is : a
-
- []用作RE中的字符范围:匹配中括号中字符集中的某一个字符。常用的可以参考如下的这些形式:[xyz]/[c-n]/[B-Pa-m]/[a-z0-9]/[^b-d](这里的^标识取反了)
- [[]]用作表达式的条件测试:它和[]的最大区别就是,内部支持&&/||/>/<等符号,这也是使得它的结构相对于[]更加通用。
4、关于整数运算扩展操作符(())
该结构允许整数运算和赋值。是Bash(注意,原生shell并不支持该结构)中C语言结构风格的一个表达式。常用的可以参考如下几种用法:((a=12))/((a++))/((++a))/((a--))/((--a))/((t = a<123?0:1)),这里需要注意两点:
- 由于(())本身的C语言语法风格,(())内部在使用Bash变量时,是不需要$前缀标识它的引用形式的。
- 注意上面例子中的最后一个,可以看出它支持多数编程语言中的典型的三元表达式哦。
5、关于重定向
Linux下,重定向输出的基本符号大家一般比较熟悉了。>表示覆盖式重定向,>>表示追加式重定向。这里需要强调的是:0,1,2这三个特殊的数字,作为3个特殊的文件描述符,已经被默认分配给了,stdin,stdout,stderr这3个特殊的“文件”。下面列出几个常用的利用重定向完成的小功能tip:
- 清空文件内容: : >a.txt 清空a.txt文件的内容。(这里某些shell下,省略前面的冒号,直接使用 >a.txt也可以,但不是所有shell都支持这种语法,所以通用性不用加上冒号的版本)
- 重定向错误输出到特定的文件中:比如,command 2>a.txt,执行command命令,同时将产生的错误输出信息,从终端中冲定向到a.txt中。
- 将标准和错误输出全部输出到特定文件中:比较典型的用法就是不关心命令的任何输出,将所有输出信息都丢入垃圾桶:command >/dev/null 2>&1。这个表达式如果不理解含义,很容易记错,误用成下面这个样子:
- command 2>&1 >/dev/null 这个表达式只能保证将stdout丢掉,但是如果有错误产生,还是会输出到屏幕上。原因是:命令解释到command 2>&1是,表示将stderr输出到stdout上(就是屏幕上),后面执行到>/dev/null时,表示将stdout输出丢掉。但是,在这之前,stderr已经被重定向到了当时的stdout(就是屏幕),所以这时的错误信息并不会丢掉,还是会输出到屏幕。
- 如果你已经决定不关心任何命令的输出信息,又觉得上面的写法有点啰嗦,那可以试试这个写法: command &>/dev/null 这个写法会不管三七二十一,直接把所有输出信息全部重定向到/dev/null,这里完全省略了默认的文件描述符1和2.
相关推荐
sqlite-shell-win32-x86-3080200.zip sqlite的windows版本
1. 内嵌数据库一般是用sqlite进行轻量级管理的。网上可以下到sqlite-shell-win32-x86: sqlite3.exe 2. 为了方便命令行执行,将sqlite3.exe放到svn 项目的主目录下,和.svn目录同级下。 3. 执行 sqlite3 .svn/wc.db ...
1. 内嵌数据库一般是用sqlite进行轻量级管理的。网上可以下到sqlite-shell-win32-x86: sqlite3.exe 2. 为了方便命令行执行,将sqlite3.exe放到svn 项目的主目录下,和.svn目录同级下。 3. cmd进入该目录下,执行 ...
csapp-shell-labcsapp-shell-labcsapp-shell-labcsapp-shell-labcsapp-shell-labcsapp-shell-labcsapp-shell-labcsapp-shell-labcsapp-shell-labcsapp-shell-labcsapp-shell-labcsapp-shell-labcsapp-shell-labcsapp...
mysql-shell-8.0.18-windows-x86-64bit.zip MySQL Shell is an advanced command-line client and code editor for MySQL. In addition to SQL, MySQL Shell also offers scripting capabilities for JavaScript ...
Linux-shell编程06Linux-shell编程06Linux-shell编程06Linux-shell编程06Linux-shell编程06Linux-shell编程06Linux-shell编程06Linux-shell编程06Linux-shell编程06Linux-shell编程06
sqlite-shell-win32-x86-3071602.zip
SQLite 是一个软件库,实现了自给自足的、无服务器的、零配置的、事务性的 SQL 数据库引擎。SQLite 是在世界上最广泛部署的 SQL 数据库引擎。SQLite 源代码不受版权限制。
以shell脚本的形式写一个统计1-100以内的奇偶数的和与个数。
最新的sqlite3 下载方便在win上面使用 sqlite-shell-win32-x86-3080403
根据网易云课堂中shell教学视频,记录的学习笔记 方便自己回忆总结
linux运维学习笔记:企业Shell面试题总结-1
1,shell 是大小写敏感的,空格敏感的! a!=A a=1(正确)a = 1(错误) 2,清屏命令 clear ?3,declare -x variable 设置环境变量 与普通变量的区别在于可以在之后的其他脚本和程序中使用。 4,双引号(“”)存在...
mysql linux shell
官方离线安装包,亲测可用。使用rpm -ivh [rpm完整包名] 进行安装
shell编程入门经典--LINUX与UNIX Shell编程指南 (中文pdf版)
Linux新手生存笔记[10]——shell脚本基础3-函数及常用命令.pdf
中文shell十三问--shell入门 第三种变量的替换方法是只有当变量已赋值时才用指定值替换形式: ${variable: +value} 只有变量variable已赋值时,其值才用value替换,否则不进行任何替换,例如: $ERROPT=A $...
最新版的sqlite-shell-win32