sed -n '/aaa/{n;p;}' filename 2、删除当前行与下一行的内容:
sed -i '/aaa/{N;d;}' filename 3、 删除当前行与下两行的内容:
sed -i '/aaa/{N;N;d;}' filename
依次类推,删除三行,则为{N;N;N;d;},分析知:N为next 4、得出以空格为分割的字符串中单词的个数,即统计个数: awk ' { print NF } '
如显示字符串VALUE中的单词个数,其中VALUE为:aaa bbb ccc ddd ee f 则执行 echo $VALUE | awk ' { print NF } ' 后的结果为6
5、在linux中建立一个文件与另一文件的链接, 即符号链接
ln -s /var/named/chroot/etc/named.conf named.conf
这要就建立了当前目录的文件named.conf对/var/named/chroot/etc/named.conf 的符号链接。即操作named.conf就意味着操作实际文件/var/named/chroot/etc/named.conf ,这时用ll命令查看的结果如:
lrwxrwxrwx 1 root root 32 Mar 22 12:29 named.conf -> /var/named/chroot/etc/named.conf
注意:当用sed来通过named.conf来删除一部分信息时,会将符号链接的关系丢掉,即会将named.conf变成一个实际文件。所以 需对实际文件进行删除操作。 6、显示指定字符范围内的内容:
如:显示文件test.txt中字符#test begin与#test end之间所有的字符 sed -n \"/#test begin/,/#test end/p\" test.txt 或 awk \"/#test begin/,/#test end/\" test.txt
在日常系统管理工作中,需要编写脚本来完成特定的功能,编写shell脚本是一个基本功了! 在编写的过程中,掌握一些常用的技巧和语法就可 以完成大部分功能了,也就是2/8原则. 1. 单引号和双引号的区别
单引号与双引号的最大不同在于双引号仍然可以引用变量的内容,但单引号内仅是普通字符 ,不会作变量的引用,直接输出字符窜。请看如下例子: [root@linux ~]# name=HaHa [root@linux ~]# echo $name HaHa
[root@linux ~]# myname=\"$name is wow\" [root@linux ~]# echo $myname HaHa is wow
[root@linux ~]# myname='$name is wow' [root@linux ~]# echo $myname $name is wow
从上面例子可以看出,使用了单引号的时候,那么$name只是普通字符,直接输出而已!
2. 逐行读取文件
使用for循环来读取文件 for line in `cat file.txt` do
echo $line done
注意:由于使用for来读入文件里的行时,会自动把空格和换行符作为一样分隔符,如果行里有空格的时候,输出的结果会很乱,所以 只适用于行连续不能有空格或者换行符的文件 使用while循环读取文件 cat file.txt |while read line do
echo $line done
或者:
while read line do
echo $line
done < file.txt
注意:由于使用while来读入文件里的行时,会整行读入,不会关注行的内容(空格..),所以比for读文件有更好的适用性, 推荐使用while循环读取文件
3. bash shell 脚本中常用隐含变量 $0 当前执行的脚本或者命令名称 $1-$9 代表参数的位置. 举例 $1 代表第一个参数. $# $@ $* $$ $? $! 脚本调用的参数的个数 所有参数的内容 所有参数的内容 当前运行脚本的进程号 命令执行后返回的状态 后台运行的最后一个进程号 注意: $? 用于检查上一个命令执行是否正确(在Linux中,命令退出状态为0表示该命令正确执行,任何非0值表示命令出错)
$$ 变量最常见的用途是用做暂存文件的名字以保证暂存文件不会重复。
$* 和 $@ 如果输出是一样的,但是在使用for循环,在使用 双引号(\"\")引用时 \"$*\" 会输出成一个元素 而 \"$@\" 会按照每个参数是一个元素方式输出 请看测试例子
#cat test.sh #!/bin/sh
echo '\"$@\" output.....' for i in \"$@\" do
echo $i done
echo '\"$*\" output ....' for i in \"$*\" do
echo $i done 输出结果
#sh test.sh a b c d \"$@\" output..... a b c d
\"$*\" output .... a b c d
从输出结果可以看出 \"$*\" 输出是一行 而 \"$@\" 输出则是四行
4. 变量内容的删除与替换
我们在一些情况下,需要对变量中的字符窜进行查找删除或者替换,就需要使用下表列出的方法
变量设定方式 ${变量#关键字} ${变量##关键字} ${变量%关键字} ${变量%%关键字} ${变量/旧字串/新字串} ${变量//旧字串/新字串} 说明 若变量内容从头开始的资料符合‘关键字’,则将符合的最短资料删除 若变量内容从头开始的资料符合‘关键字’,则将符合的最长资料删除 若变量内容从尾向前的资料符合‘关键字’,则将符合的最短资料删除 若变量内容从尾向前的资料符合‘关键字’,则将符合的最长资料删除 若变量内容符合‘旧字串’则‘第一个旧字串会被新字串取代 若变量内容符合‘旧字串’则‘全部的旧字串会被新字串取代 举例如下(删除字符窜中的某个字符): [root@linux ~]# export
test_str=\"/usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin\"
[root@linux ~]# echo ${test_str#/*kerberos/bin:}
/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin
5. 变量条件测试赋值
在某些时刻我们需要‘判断’某个变量是否存在,若变量存在则将此变量值赋值给新的变量,若变量不存在则将其他值赋值给新的变量.
变量设定方式 var=${str-expr} var=${str:-expr} var=${str+expr} var=${str:+expr} var=${str?expr} var=${str:?expr} var=${str=expr} var=${str:=expr} 举例如下: [root@linux ~]# test_name=\"\"
[root@linux ~]# test_name=${test_name-root} [root@linux ~]# echo $test_name
<== 因为 test_name 被设定为空字符窜!所以当然还是保留为空字符窜! [root@linux ~]# test_name=${test_name:-root} [root@linux ~]# echo $test_name
root <== 加上‘:’后若变量内容为空或者是未设定,都能够以后面的内容替换!
基本上这种变量的测试也能够透过 shell script 内的 if...then... 来处理,不过通过上述提及的简单的方法来测试变量,是程序看起来更精简一些!
str 未定义 var=expr var=expr var= var= expr 输出至 stderr expr 输出至 stderr var=expr var=expr str 为空字串 var= var=expr var=expr var= var= expr 输出至 stderr var= var=expr str 已赋值为非空字串 var=$str var=$str var=expr var=expr var=$str var=$str var=$str var=$str 6. shell 中分隔符 : 变量IFS 使用
shell脚本中,如果使用for循环一个字符窜的话,默认使用空格来分割字符窜.还有前面所提到的 使用for循环逐行读取文件内容时候,文件行中如果有空格的话输出的结果也会变乱.这个时候 使用 IFS 变量来设置特定的字符窜分割符来,达到输出正确的目的.默认情况下 IFS 是使用 我们将前面使用for逐行读取文件的例子 改进下就可以输出正确了,请看下面 #!/bin/bash IFS_old=$IFS #将原IFS值保存,以便用完后恢复 IFS=$’\\n’ #更改IFS值为$’\\n’ for line in `cat file.txt` do echo $line done file.txt 文件内容如下 [root@linux]$ cat file.txt sdfsdfsdfsdf ssssss ssssss ssssss sssss sdfsdfsdfsdfsdf 执行测试程序 输出结果如下(正确输出) [root@linux]$ sh test.sh sdfsdfsdfsdf ssssss ssssss ssssss sssss sdfsdfsdfsdfsdf 如果未设置IFS变量,使用默认的IFS变量值 ,输出结果如下 [root@linux]$ sh test.sh sdfsdfsdfsdf ssssss ssssss ssssss sssss sdfsdfsdfsdfsdf 从以上测试程序输出结果,可以根据自己的需求来设定 IFS变量,在举一个例子如下: while IFS=: read userName passWord userID groupID geCos homeDir userShell do echo \"$userName -> $homeDir\" done < /etc/passwd 7. shell 数组的使用 数组赋值方式: (1) array=(var1 var2 var3 ... varN) (2) array=([0]=var1 [1]=var2 [2]=var3 ... [n]=varN) (3) array[0]=var1 arrya[1]=var2 ... array[n]=varN 计算数组元素个数或者长度: (1) ${#array[@]} (2) ${#array[*]} 了解了数组基础语法,举例说明,请看: #!/bin/bash NAMESERVERS=(\"ns1.www.net.\" \"ns2.www.net.\" \"ns3.www.net.\") # 得到数组长度 tLen=${#NAMESERVERS[@]} # 循环数组 for (( i=0; i<${tLen}; i++ )); do echo ${NAMESERVERS[$i]} done 在看一个复杂一点的例子,将文件内容读取到数组中: #!/bin/bash # 设置IFS将分割符 设置为 换行符(\\n) OLDIFS=$IFS IFS=$'\\n' # 读取文件内容到数组 fileArray=($(cat file.txt)) # restore it IFS=$OLDIFS tLen=${#fileArray[@]} # 循环显示文件内容 for (( i=0; i<${tLen}; i++ )); do echo \"${fileArray[$i]}\" done 8. 逻辑判断 条件测试 文件属性的判断 操作符 -e filename -r filename -w filename -x filename -o filename -z filename -f filename -d filename 测试结果 文件存在返回1, 否则返回0 文件可读返回1,否则返回0 文件可写返回1,否则返回0 文件可执行返回1,否则返回0 文件属于用户本人返回1, 否则返回0 文件长度为0返回1, 否则返回0 文件为普通文件返回1, 否则返回0 文件为目录文件时返回1, 否则返回0 举例如下,测试文件是否存在: #!/bin/bash echo \"checks the existence of the messages file.\" echo -n \"Checking...\" if [ -f /var/log/messages ];then echo \"/var/log/messages exists.\" fi echo echo \"...done.\" 字符串比较 操作符 str1 = str2 str1 != str2 -n str1 -z str1 str 比较结果 当两个字串相等时为真 当两个字串不等时为真 当字符串的长度大于0时为真 当字符串的长度为0时为真 当字符串为非空时为真 举例如下,比较字符串来测试用户ID : if [ \"$(whoami)\" != 'root' ]; then echo \"You have no permission to run $0 as non-root user.\" exit 1; fi 数值比较(整数) 操作符 num1 -eq num2 num1 -ne num2 num1 -gt num2 num1 -ge num2 num1 -lt num2 num1 -le num2 举例如下: num=`wc -l work.txt` if [ $num -gt 150 ];then echo \"you've worked hard enough for today.\" echo fi 如果要查看详细的测试操作,可以查看man手册 man test 如何用脚本实现分割文件 CODE: [Copy to clipboard] #!/bin/bash 比较结果 两数相等为真 两数不等为真 num1大于num2为真 num1大于等于num2为真 num1小于num2为真 num1小于等于num2为真 if [ $# -ne 2 ]; then echo 'Usage: split file size(in bytes)' exit fi file=$1 size=$2 if [ ! -f $file ]; then echo \"$file doesn't exist\" exit fi #TODO: test if $size is a valid integer filesize=`/bin/ls -l $file | awk '{print $5}'` echo filesize: $filesize let pieces=$filesize/$size let remain=$filesize-$pieces*$size if [ $remain -gt 0 ]; then let pieces=$pieces+1 fi echo pieces: $pieces i=0 while [ $i -lt $pieces ]; do echo split: $file.$i: dd if=$file of=$file.$i bs=$size count=1 skip=$i let i=$i+1 done echo \"#!/bin/bash\" >; merge echo \"i=0\" >;>; merge echo \"while [ $i -lt $pieces ];\" >;>; merge echo \"do\" >;>; merge echo \" echo merge: $file.$i\" >;>; merge echo \" if [ ! -f $file.$i ]; then\" >;>; merge echo \" echo merge: $file.$i missed\" >;>; merge echo \" rm -f $file.merged\" >;>; merge echo \" exit\" >;>; merge echo \" fi\" >;>; merge echo \" dd if=$file.$i of=$file.merged bs=$size count=1 seek=$i\" >;>; merge echo \" let i=$i+1\" >;>; merge echo \"done\" >;>; merge chmod u+x merge' 如何查找日期为某一天的文件 CODE: [Copy to clipboard] #!/bin/sh # The right of usage, distribution and modification is here by granted by the author. # The author deny any responsibilities and liabilities related to the code. # OK=0 A=`find $1 -print` if expr $3 == 1 >;/dev/null ; then M=Jan ; OK=1 ; fi if expr $3 == 2 >;/dev/null ; then M=Feb ; OK=1 ; fi if expr $3 == 3 >;/dev/null ; then M=Mar ; OK=1 ; fi if expr $3 == 4 >;/dev/null ; then M=Apr ; OK=1 ; fi if expr $3 == 5 >;/dev/null ; then M=May ; OK=1 ; fi if expr $3 == 6 >;/dev/null ; then M=Jun ; OK=1 ; fi if expr $3 == 7 >;/dev/null ; then M=Jul ; OK=1 ; fi if expr $3 == 8 >;/dev/null ; then M=Aug ; OK=1 ; fi if expr $3 == 9 >;/dev/null ; then M=Sep ; OK=1 ; fi if expr $3 == 10 >;/dev/null ; then M=Oct ; OK=1 ; fi if expr $3 == 11 >;/dev/null ; then M=Nov ; OK=1 ; fi if expr $3 == 12 >;/dev/null ; then M=Dec ; OK=1 ; fi if expr $3 == 1 >;/dev/null ; then M=Jan ; OK=1 ; fi if expr $OK == 1 >; /dev/null ; then ls -l --full-time $A 2>;/dev/null | grep \"$M $4\" | grep $2 ; else echo Usage: $0 path Year Month Day; echo Example: $0 ~ 1998 6 30; fi 如何计算当前目录下的文件数和目录数 CODE: [Copy to clipboard] # ls -l * |grep \"^-\"|wc -l ---- to count files # ls -l * |grep \"^d\"|wc -l ----- to count dir 如何只列子目录? CODE: [Copy to clipboard] ls -F | grep /$ 或者 alias sub = \"ls -F | grep /$\"(linux) ls -l | grep \"^d\" 或者 ls -lL | grep \"^d\" (Solaris)如何实现取出文件中特定的行内容 CODE: [Copy to clipboard] 如果你只想看 文件的前5行,可以使用head命令, 如: head -5 /etc/passwd 如果你想查看文件的后10行,可以使用 tail命令, 如: tail -10 /etc/passwd 你知道怎么查看文件中间一段吗?你可以使用sed命令 如: sed -n '5,10p' /etc/passwd 这样你就可以只查看文件的第5行到第10行。如何查找含特定字符串的文件 CODE: [Copy to clipboard]例如查找当前 目录下含有\"the string you want find...\"字符串的文件: $find . -type f -exec grep “the string you want find...” {} ; -print 如何列出目录树 CODE: [Copy to clipboard] 下面的短小的 shell程序可以列出目录树, 充分利用了sed强大的模式匹配能力. 目录树形式如下: . `----shellp `----updates `----wu-ftpd-2.4 | `----doc | | `----examples | `----src | | `----config | | `----makefiles | `----support | | `----makefiles | | `----man | `----util 脚本如下: #!/bin/sh # dtree: Usage: dtree [any directory] dir=${1:-.} (cd $dir; pwd) find $dir -type d -print | sort -f | sed -e \"s,^$1,,\" -e \"/^$/d\" -e \"s,[^/]*/([^/]*)$,`----1,\" -e \"s,[^/]*/,| ,g\" 如何实现取出文件中特定的列内容 CODE: [Copy to clipboard] 我们经常会遇 到需要取出分字段的文件的某些特定字段,例如/etc/password就是通过“:”分隔各个字段的。可以通过cut命令来实现。例如,我们希望将系统 账号名保存到特定的文件,就可以: cut -d: -f 1 /etc/passwd >; /tmp/users -d用 来定义分隔符,默认为tab键,-f表示需要取得哪个字段。 当然也可以通过cut取得文件中每行中特定的几个字符,例如: cut -c3-5 /etc/passwd 就是输出/etc/passwd文件中每行的第三到第五个字符。 -c 和 -f 参数可以跟以下子参数: N 第N个字符或字段 N- 从第一个字符或字段到文件结束 N-M 从第N个到第M个字符或字段 -M 从第一个到第N个字符或字段 在vim中实现批量加密 CODE: [Copy to clipboard] 密码中还是不 能带空格,不管了,能加密就好,先这么用着。 ============================================================ #!/bin/bash # Encrypt file with vim if (test $# -lt 2) then echo Usage: decrypt password filename else vim -e -s -c \":set key=$1\" -c ':wq' $2 echo \"$2 encrypted.\" fi ============================================================ [weeder@SMTH weeder]$ for file in *.txt ; do encrypt test $file ; done test2.txt encrypted. test4.txt encrypted. test9.txt encrypted. kick.txt encrypted. echo \"$2 encrypted.\" fi [weeder@SMTH weeder]$ for file in *.txt ; do encrypt test $file ; done test2.txt encrypted. test4.txt encrypted. test9.txt encrypted. kick.txt encrypted. too_old.txt encrypted. too_old_again.txt encrypted. bg5.txt encrypted. [weeder@SMTH weeder]$ $@等特定shell变量的含义 CODE: [Copy to clipboard] 在shell 脚本的实际编写中,有一些特殊的变量十分有用: $# 传递到脚本的参数个数 $* 以一个单字符串显示所有向脚本传递的参数。与位置变量不同,此选项参数可超过9个 $$ 脚本运行的当前进程ID号 $! 后台运行的最后一个进程的进程ID号 $@ 与$#相同,但是使用时加引号,并在引号中返回每个参数 $- 显示shell使用的当前选项,与set命令功能相同 $? 显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。如何使程序的执行结果同时定向到屏幕和文件 CODE: [Copy to clipboard] program_name |tee logfile 这样程序执行期间的显示都记录到logfile同时显示到标准输出(屏幕)。 如何用sendmail给系统所有用户送信 CODE: [Copy to clipboard] 首先在 aliases文件里面建立一个alias: alluser: :include:/etc/mail/allusers 并执行 newaliases使之生效,然后在/etc/mail/allusers里面列出所有用户,可以使用下面的命令: awk -F: '$3 >; 100 { print $1 }' /etc/passwd >; /etc/mail/allusers如何查找某条命令的相关库文件 CODE: [Copy to clipboard] 在制作自己的 发行版时经常需要判断某条命令需要哪些库文件的支持,以确保指定的命令在独立的系统内可以可靠的运行。 在Linux环境下通过ldd命令即可实 现,在控制台执行: ldd /bin/ls 即可得到/bin/ls命令的相关库文件列表。 如何使用host命令获得更多信息 CODE: [Copy to clipboard] Host能够 用来查询域名,然而它可以得到更多的信息。host -t mx linux.com可以查询出Linux.com的MX记录,以及处理Mail的Host的名字。Host -l linux.com会返回所有注册在linux.com下的域名。host -a linux.com则会显示这个主机的所有域名信息。 如何停止终端多个进程 CODE: [Copy to clipboard] 以下是脚本: echo \"系统当前用户\" echo \"---------------\" who | awk '{print $2}' echo \"---------------\" echo \"输入要杀死终端的终端号:\" read $TTY kill -9 ${K}=`ps -t $TTY | grep [0-9] | awk '{print $1}'` 如何转存用户bash_history文件 # 把以下代码添加到/etc/profile文件内 export HISTTIMEFORMAT=\"%F %T \" USER_IP=`who -u am i 2>/dev/null| awk '{print $NF}'|sed -e 's/[()]//g'` LOCAL_name=`hostname` HISTDIR=/var/log/.hist/${LOCAL_name}_`date +%Y%m%d`_auditlog # 判断$USER_IP是否为空,如果为空则使用hostname记录. if [ -z $USER_IP ] then USER_IP=`hostname` fi if [ ! -d $HISTDIR ] then mkdir -p $HISTDIR # 为$HISTDIR赋值权限,让所有用户都可以访问. chmod 777 $HISTDIR fi if [ ! -d $HISTDIR/${LOGNAME} ] then mkdir -p $HISTDIR/${LOGNAME} chmod 300 $HISTDIR/${LOGNAME} fi export HISTSIZE=4096 DT=`date +%Y%m%d\"_\"%T` export HISTFILE=\"$HISTDIR/${LOGNAME}/${USER_IP}_${LOGNAME}_$DT\" chmod 600 $HISTDIR/${LOGNAME}/*.hist* 2>/dev/null 2009年04月28日Program, Shell shell 技巧 脚本 shell常用技巧 用自动导入函数的方法,可以在命令行下像执行命令一样快捷,而且速度快,占用资源少. 1,建立自己的函数库 mkdir functionlib 然后将常用的脚本改成函数的语法,如: function filename { command ; } 将filename拷贝到functionlib中, 2,修改环境文件,在/etc/profile中添加 export FPATH=$HOME/functionlib 3,重登录一下 这样的话,你就可以随时用像ls那样运行你自己的filename”命令” 而不需要用什么dot,sh,来运行你的函数/脚本啦~~ 如果在脚本中运行,可以在脚本顶部用 #!/bin/sh ## autoload filename //来自动导入函数. „ filename //调用函数 „ 用自动导入函数的方法,可以在命令行下像执行命令一样快捷,而且速度快,占用资源少. 1,建立自己的函数库 mkdir functionlib 然后将常用的脚本改成函数的语法,如: function filename { command ; } 将filename拷贝到functionlib中, 2,修改环境文件,在/etc/profile中添加 export FPATH=$HOME/functionlib 3,重登录一下 这样的话,你就可以随时用像ls那样运行你自己的filename”命令” 而不需要用什么dot,sh,来运行你的函数/脚本啦~~ 如果在脚本中运行,可以在脚本顶部用 #!/bin/sh ## autoload filename //来自动导入函数. „ filename //调用函数 „ 技巧:pkill的妙用 ——————————————————————————– 有的时候有很多进程或运行或睡眠或僵死,占用了很多宝贵的内存空间,kill固然可以杀掉某些进程,但更好的方法是用pkill,举例: 代码: root//root>ps -A PID TTY TIME CMD „ 1045 ? 00:00:00 kdeinit 1052 ? 00:00:00 kdeinit 1054 pts/0 00:00:00 xterm 1056 pts/1 00:00:00 bash 1082 pts/0 00:00:00 ps root//root>free total used free shared buffers cached Mem: 252340 212036 40304 0 5752 103200 -/+ buffers/cache: 103084 149256 Swap: 610460 0 610460 root//root>pkill -9 xterm;free [1]+ Killed xterm total used free shared buffers cached Mem: 252340 210776 41564 0 5760 103200 -/+ buffers/cache: 101816 150524 Swap: 610460 0 610460 在我杀掉了xterm这个进程后,看看你的free内存空间相应增加不少?. 详细使用方法请: man pkill or pkill –help 用stty和dd实现暂停,只须按一个键就可. #!/bin/ksh # function char { settty=$(stty -g) stty raw dd if=/dev/tty bs=1 count=1 2> /dev/null stty -raw stty $settty } print “Press any key to continue„” input=$(char) 技巧:如何检查用户的输入? ——————————————————————————– 有的时候,我们对用户的输入要作必要的检测,如,限制输入的长度/类型.举例说明: 代码: #!/bin/ksh #要求用户必须输入四个数字 while true do echo -n “请输入四个数字:” read num len=${#num} #变量len存放输入的长度 if [[ $num != [0-9][0-9][0-9][0-9] || $len != 4 ]] then #进行检测,如果你输入有非数字字符,或者长度不等于四个,便提示错误信息 echo “错误! 重新输入” continue else echo “输入正确,退出!”;exit 0 fi done 这是个例子,在我们编写脚本中可以借鉴 shell变量传递给sed,awk,grep简单方法 ——————————————————————————– 有时候在脚本编写中,需要往诸如awk等工具中传递shell的变量,举个简单的例子,如: ps -aux|sed -n 1p read input?”please field number your want to see:” ps -aux|awk ‘{print $”‘${input}’”}’ read enter?”please line number your want to see:” ps -aux|sed -n ${enter}p read user?”please username your want to see:” ps -aux|grep $user 注:上述文件无实际意义,只为说明而已. 开启小键盘数字灯的方法 ——————————————————————————– 在man setleds的描述中,有一段设置字符控制台数字灯的脚本: 代码: INITTY=/dev/tty[1-8] for tty in $INITTY do setleds -D +num < $tty done 把它放在/etc/rc.d/rc.local文件中即可!这样就可以像WIN一样一启动系统,它的小键盘的数字灯总是打开的! 在字符模式下,也可以这样: setleds -D +num/+caps/+scroll 技巧:把输入的密码变成*号的方法 -------------------------------------------------------------------------------- 注:此贴转自:WWW.CHINAUNIX.NET 代码: #!/bin/sh getchar() { stty cbreak -echo dd if=/dev/tty bs=1 count=1 2> /dev/null stty -cbreak echo } printf “Please input your passwd: ” while : ; do ret=`getchar` if [ -z $ret ]; then echo break fi str=”$str$ret” printf “*” done echo “Your password is: $str” 技巧:数值转换 ——————————————————————————– 代码: #!/bin/bash #scriptname:conver #在BASH下简单实现十进制到二进制和十六进制的转换 cat< 技巧:统计文本中单词数量的方法 ——————————————————————————– 有些单词在一篇文章中经常会出现很多次,怎么统计这个单词的个数呢?! 如:文件kshfile,统计shell这个单词的个数, $cat kshfile ksh The “Korn” shell, written by David Korn of AT&T Bell Labs (now Lucent). Written as a major upgrade to “sh”, it is compatible with it, but has many more internal commands for the most frequently used functions. It also incorporates most of the same features from tcsh which enhance interactive use (command line history recall etc.). This shell is now available on most systems. It was slow to gain acceptance because earlier versions were encumbered by AT&T licensing. $cat kshfile|tr ” ” ” “|grep -wc shell 2 技巧:显示文本奇数偶数的方法 ——————————————————————————– [javalee//home/javalee/myshell]cat tmp aaaaaa dddddd kasdkfkk djhasdjf dfddf kjsdfklkls asdfjklkas #显示文件tmp的奇数行的内容: [javalee//home/javalee/myshell]sed -n ‘1,$p;n’ tmp aaaaaa kasdkfkk dfddf asdfjklkas #显示文件tmp的偶数行的内容: [javalee//home/javalee/myshell]sed -n ‘1,$n;p’ tmp dddddd djhasdjf kjsdfklkls 技巧:倒读文本 ——————————————————————————– 例如文章: $cat -n tmp 1 abcdefgh 2 123234234 3 sjdfk23423 1,行号倒序: $cat -n tmp|tac #tac和cat很有趣吧~~ 3 sjdfk23423 2 123234234 1 abcdefgh 2,每行倒读: $cat tmp|rev hgfedcba 432432321 32432kfdjs 3,全部倒过来: $cat -n tmp|rev|tac 32432kfdjs 3 432432321 2 hgfedcba 1 4,用sed也可以解决要求对sed有足够的理解) $cat -n tmp|sed ‘/ /!G;s/(.)(.* )/&21/;//D;s/.//’ hgfedcba 1 432432321 2 32432kfdjs 3 技巧:把汉字转换成十六进制和二进制的方法 ——————————————————————————– 命令行下,利用perl的unpack函数,可以将汉字巧妙的变成十六进制和二进制,如: [javalee//home/javalee/myshell]perl -le ‘print unpack(“B*”,”中”);’ #把汉字”中”转换成二进制 1101011011010000 [javalee//home/javalee/myshell]perl -le ‘print unpack(“H*”,”国”);’ #把汉字”国”转换成十六进制 b9fa 技巧:妙用watch命令实时观察内存变化 ——————————————————————————– 在linux中,有一个很有趣的命令–watch,他的作用很有趣! 他作用是以全屏幕方式重复地执行指定的命令,用户可以通过他了解命令的运行情况. 如,我们要观察内存动态的变化,那么就可以: watch free 这样就可以动态的观察内存中各个指标在指定时间内的变化啦~~, 如要观察虚拟内存的变化,也可以通过打开另外一个终端,而不耽误当前终端的操作!: xterm -e watch -n 1 vmstat & 这样就会弹出一个xterm,显示有关虚拟内存的情况. 详细解释,请: watch –help man watch 技巧: 用 tr 过滤文件[转贴] ——————————————————————————– 了解文本实用程序 Jacek Artymiak(jacek@artymiak.com) 自由作家和顾问 2003 年 7 月 没有人曾说过 sed 很容易 – 它确实不容易!但通过使用 tr,您可以非常容易地实现 sed 的许多最基本功能。Jacek Artymiak 向您展示如何去做。 您可以将 tr 看作为 sed 的(极其)简化的变体:它可以用一个字符来替换另一个字符,或者可以完全除去一些字符。您也可以用它来除去重复字符。这就是所有 tr 所能够做的。 那么,为什么要使用 tr,而不使用 sed 呢?当然是为了使事情简单。例如,如果我们希望用字母”z”来替换出现的所有字母”a”,则可以用 tr a z,这条命令毫无疑问比 sed -e s/a/z/g 简单,尤其在把它用到脚本中时,其中的引号转义很让人头痛。另外,在使用 tr 时,可以避免写那些让人讨厌的正则表达式。 使用 tr 很简单:使用前面一段中所给出的符号表示法,用一个字符去替换出现的所有另一个字符。当需要替换多个字符时,使用类似于这样的表示法:tr abc xyz,它表示用字母”x”去替换出现的所有字 母”a”,用字母”y”去替换所有字母”b”,用字母”z”去替换所有字母”c”。这两组中所列出的字符的 数目不必相等。 您也可以指定字符的范围。例如,tr a-z A-Z 将用对应的大写字母来替换所有的小写字母(例如,它 将”no smoking”转换成”NO SMOKING”)。当您在 vi 编辑器中想强调正在编辑的文本的某一部分时,使用这一特殊技巧非常方便。只要按一下 Escape 键,然后按 : 键,再输入 2,4!tr ‘a-z’ ‘A-Z’,最后按一下 Return 键。现在,从第 2 行到第 4 行的字母就都转换成了大写字母。 关于 tr 的其它内容 GNU 手册上提到,tr 在执行您所选择的操作时,通过将标准输入复制到标准输出,从而实现”转换、压缩和/或删除字符”。在这篇技巧文章中,您将了解到这些选项;当然也可以通过 了解 tr 的手册页或信息页,学习到更多关于 tr 的内容。 打开一个新的终端窗口,输入 man tr 或 info tr – 或者打开一个新的浏览器窗口,并链接到 gnu.org 上的 tr 手册页(关于这个链接,请参阅参考资料)。 另外,当有人给您发送了一个在 Mac OS 或 DOS/Windows 机器上创建的文本文件时,您会发现 tr 非常有用。如果没有将文件保存为使用 UNIX 换行符来表示行结束这种格式,则需要将这样的文件转换成本机 UNIX 格式,否则一些命令实用程序不会正确地处理这些文件。Mac OS 的行尾以回车字符结束,许多文本处理工具将这样的文件作为一行来处理。为了纠正这个问题,可以用下列技巧: Mac -> UNIX:tr ‘ ‘ ‘ ‘ < macfile > unixfile UNIX -> Mac:tr ‘ ‘ ‘ ‘ < unixfile > macfile Microsoft DOS/Windows 约定,文本的每行以回车字符并后跟换行符结束。为了纠正这个问题,可以使用下列命令: DOS -> UNIX:tr -d ‘ ‘ < dosfile > unixfile UNIX -> DOS:在这种情况下,需要用 awk,因为 tr 不能插入两个字符来替换一个字符。要使用的 awk 命令为 awk ‘{ print $0″ ” }’ < unixfile > dosfile 另外,当您需要对文本文件做一些简单的整理工作(如用 tr -d ‘ ‘ 除去制表符,用 tr -s ‘ ‘ 除去多余的空格,或者用 tr -d ‘ ‘ 将分开的几行合成一行)时,会需要用 tr。同样,可以在 vi 内使用所有这些命令;只要记住:在 tr 命令前要加上您希望处理的行范围和感叹号(!),如 1,$!tr -d ‘ ‘(美元符号表示最后一行)中所示。 技巧:删除文件中空行的几种方法 ——————————————————————————– 1,cat filename|tr -s ‘ ‘ 2,sed ‘/^$/d’ filename 3,awk ‘{if($0!=”\")print}’ filename 4,用grep也可以,但是比较麻烦 技巧:如何判断输入的是字符还是数字的三个方法 ——————————————————————————– 1,用输入的字符串和任意一个数字进行运算,可以判断! 代码: #!/bin/ksh # var=$(echo “$1*1″|bc) if [[ $var != 0 ]] then echo “$1 is a number” else echo “$1 is a charter” fi 2,用流编辑器sed! 代码: if [ -n \"`echo $1|sed -n '/^[0-9][0-9]*$/p’`” ] then echo “$1 is number!” else echo “$1 is not number!” fi 3,用awk来判断! 代码: echo $1|awk ‘{if($0~/[^0-9]/) {print “‘$1′ is not number”} else{print “‘$1′ is number”}}’ 技巧:用 uniq 除去重复行[转] ——————————————————————————– 作者:Jacek Artymiak(jacek@artymiak.com)自由作家和顾问 2003 年 7 月 重复行通常不会造成问题,但是有时候它们的确会引起问题。此时,不必花上一个下午的时间来为它们编制过滤器,uniq 命令便是唾手可得的好工具。了解一下它是如何节省您的时间和精力的。 进行排序之后,您会发现有些行是重复的。有时候该重复信息是不需要的,可以将它除去以节省磁盘空间。不必对文本行进行排序,但是您应当记住 uniq 在读取行时会对它们进行比较并将只除去两个或更多的连续行。下面的示例说明了它实际上是如何工作的: 清单 1. 用 uniq 除去重复行 $ cat happybirthday.txt Happy Birthday to You! Happy Birthday to You! Happy Birthday Dear Tux! Happy Birthday to You! $ sort happybirthday.txt Happy Birthday Dear Tux! Happy Birthday to You! Happy Birthday to You! Happy Birthday to You! $ sort happybirthday.txt | uniq Happy Birthday Dear Tux! Happy Birthday to You! 警告:请不要使用 uniq 或任何其它工具从包含财务或其它重要数据的文件中除去重复行。在这种情况下,重复行几乎总是表示同一金额的另一个交易,将它除去会给会计部造成许多困难。 千万别这么干! 有关 uniq 的更多信息 本系列文章介绍了文本实用程序,它对在手册页和信息页找到的信息作了补充。如果您打开新的终端窗口并输入 man uniq 或 info uniq,或者打开新的浏览器窗口并查看位于 gnu.org 的 uniq 手册页,那么就可以了解更多的相关信息。 如果您希望您的工作轻松点,比如只显示唯一的或重复的行,那么该怎么办呢?您可以用 -u(唯一)和 -d(重复)选项来做到这一点,例如: 清单 2. 使用 -u 和 -d 选项 $ sort happybirthday.txt | uniq -u Happy Birthday Dear Tux! $ sort happybirthday.txt | uniq -d Happy Birthday to You! 您还可以用 -c 选项从 uniq 中获取一些统计信息: 清单 3. 使用 -c 选项 $ sort happybirthday.txt | uniq -uc 1 Happy Birthday Dear Tux! $ sort happybirthday.txt | uniq -dc 3 Happy Birthday to You! 就算 uniq 对完整的行进行比较,它仍然会很有用,但是那并非该命令的全部功能。特别方便的是:使用 -f 选项,后面跟着要跳过的字段数,它能够跳过给定数目的字段。当您查看系统日志时这非常有用。通常,某些项要被复制许多次,这使得查看日志很难。使用简单的 uniq 无法完成任务,因为每一项都以不同的时间戳记开头。但是如果您告诉它跳过所有的时间字段,您的日志一下子就会变得更加便于管理。试一试 uniq -f 3 /var/log/messages,亲眼看看。 还有另一个选项 -s,它的功能就像 -f 一样,但是跳过给定数目的字符。您可以一起使用 -f 和 -s。uniq 先跳过字段,再跳过字符。如果您只想使用一些预先设置的字符进行比较,那么该怎么办呢?试试看 -w 选项。 技巧:限时输入的实现 ——————————————————————————– 举例: 代码: #!/bin/ksh stty -icanon min 0 time 100 <=限定时间为10秒 while do echo \"Please input:y/m/d/[ENTER]:\" <=输入字母y,m,d或者回车 read input case $input in y) date +%Y;break;; m) date +%m;break;; d) date +%d;break;; \"\") date +%Y/%m/%d;break;; <=当输入为空(回车)或者10秒钟内没有输入的话,取设定的默认值. *) echo \"wrong!again!\";continue;; esac done stty sane 技巧:查找特定字符所在行行号的方法 -------------------------------------------------------------------------------- 方法很多,介绍一下3个具有代表性的, 1,grep -n \"string\" filename 2,sed -n '/string/=' filename 3,awk '/string/{print FNR}' filename 当然,和nl配合使用效果基本一致! 在shell里进行算术运算常用的3种方法 -------------------------------------------------------------------------------- 1,expr expr 1 + 2 #注意空格 2,(()) ((n=1+2)) 3,bc echo \"1+2\"|bc #优点可以取小数点的位数 4, echo $[1+2] 隐藏回显的另一法 -------------------------------------------------------------------------------- 除了用stty -echo来禁止显示诸如密码之类的方法外,也可以尝试这样 代码: echo -n \"please input password:�33[8m\" read input echo -n �33[0m awk技巧两则 -------------------------------------------------------------------------------- 1,查找一个关键词在整个文件中出现的次数 代码: awk '/keyword/{count++}END{print count }' filename 2,替换 代码: awk '{gsub(/oldstr/,\"newstr\");print}' filename 技巧:从键盘输入生成文件的若干方法 -------------------------------------------------------------------------------- 1,用echo,如: 代码: echo \"some strings \">filename 2,用here文档,如: 代码: /home/javalee#cat #CTR+D退出 3,用dd命令,如: 代码: /home/javalee#dd filename 2>/dev/null #CTR+D退出 4,用while循环,如: 代码: /home/javalee#while read i;do echo $i >>filename;done #CTR+D退出 5,用read:如: 代码: /home/javalee#while true;do read;echo $REPLY >>filename;[[ -z $REPLY ]]&&break;done 技巧:用grep提取网址/链接的方法 ——————————————————————————– 代码: grep -o ‘http://[a-zA-Z0-9./?=%_~]*’ urlfile 感兴趣的话大家可以测试一下 grep version: grep (GNU grep) 2.5.1 grep对-o选项的解释: -o, –only-matching show only the part of a line matching PATTERN 常用shell脚本的使用 shell, 脚本 我在学习期间写过一些shell脚本,现在整理出来,希望对刚学习shell的朋友有点用处: 测试过程:vi test.sh 后把程序写入其中,保存退出。然后改变文件属性:chmod +x test.sh 最后执行:./test.sh for语句测试: 1) #!/bin/bash for num in 1 2 3 do echo \"hello,num=$num\" done 2) #!/bin/bash for ((i=1;i<=3;i=i+1 ));do echo hello,$i;done if语句测试: #!/bin/bash echo \"please run the program with more than one param\" if [ \"$1\" = '' ] #$1是只运行该程序时可加参数1,如./iftest.sh 1 注意等号旁边和中括号的空格 then echo \"error\" else echo \"ls内容为\\n:\" #echo '$1':$1 echo `ls` fi while语句测试: 1) #!/bin/bash m=0 while [ $m -lt 10 ] do echo $m m=`expr $m + 1` #注意m旁边的空格 done 2) declare -i m=0 #别一种在算术运算时声明变量的方法 while [ $m -lt 10 ] do echo $m m=$m+1 done until语句测试: 1) #!/bin/bash declare -i m=10 until [ $m -lt 10 ] do echo $m m=$m-1 done 2) declare -i m=0 while [ $m -lt 10 ] do echo $m m=$m+1 done sed测试: #!/bin/bash #sed '/^root/ !s/bash/nologin/' /etc/passwd man sed | col -b > fortest.sh sed '1,$s/is/--end/' fortest.sh sed '1,$s/is/--end/g' fortest.sh sed '/is/=' fortest.sh 引号测试: #!/bin/bash var=hello echo \"var is $var\" echo 'var is $var' echo \"var is \\$var\" echo `ls` var2=date echo `$var2` case语句测试: #!/bin/bash for (( ;; )) do echo \"please input a key:\" read word case $word in 1) echo \"your chioce is the one\" ;; 2) echo \"your chioce is the two\" ;; 3) echo \"your chioce is the three\" ;; q) echo \"your choice is exit\" exit ;; *) echo \"illegal choice\" exit esac done \" $ \"符号测试: #!/bin/bash echo \"please run with more than one parm\"; echo \"program name \\$0:\"$0; echo \"first param \\$1:\"$2; echo \"first param \\$$:\"$$; echo \"first param \\$*:\"$*; 数组的使用: #!/bin/bash hostip=(\"100\ hostpass=(\"123456\ 3456\i=1 while [ $i -lt 12 ] ; do ssh root@10.0.2.hostip[$i] done 重启别人电脑的shell: #这个好像有点问题,需再测试下 #!/usr/bin/expect spawn ssh root@10.0.2.120 expect \"password:\" send \"123456\\n\" expect \"$\" send \"reboot\\n\" #expect \"password:\" #send \"123456\\n\" expect eof 查找文件,需指定查找目录和文件的修改时间: #!/bin/bash path=$1 date=$2 if [ -z $path ] then echo \"Please input find path:(eg:/dev/abc/)\" read path fi if [ -z $date ] then echo \"Please input find date:(eg:2006-04-23)\" read date fi ls -l $path --time-style=long-iso | grep \"$date $time\" 递归算法: 1) #!/bin/bash function myls() { local y=`ls`; echo $y; for z in $y;do if [ -d $z ];then echo \"进入子目录\"; cd `pwd`/$z; myls; echo \"返回上一级目录\"; cd..; fi done } echo \"please input a directory:\" read x cd $x myls; 2)#!/bin/bash check_dir() { if [ -d $y ];then echo \"$y是一个目录\"; ls -l $y else echo \"$y是一个文件\"; fi } echo \"please input a directory:\" read y x=`ls $y` echo $x for y in $x;do check_dir done; 备份脚本: #!/bin/bash /bin/tar -zcf /var/mail /bin/cp /var/mail.tar.gz /root 查找目录: #!/bin/bash ls -l | grep ^d #输出当前目录下的所有目录 更新ftp服务器上的文件: #!/bin/bash echo \"open 10.0.2.224\" > /tmp/ftp1.cmd echo \"user ubunadm 123456\" >> /tmp/ftp1.cmd echo \"get `date +%Y`/`date +%Y%m`/`date +%d`/file01 /root/copy/file02\" >> /tmp/ftp1.cmd ftp -nv < /tmp/ftp1.cmd echo \"quit\" >> /tmp/ftp1.cmd echo \"open 10.0.2.224\" > /tmp/ftp.cmd echo \"user ubunadm 123456\" >> /tmp/ftp.cmd j=`date +%Y`/`date +%Y%m`/`date +%d` echo \"$j\" echo \"cd $j\" >> /tmp/ftp.cmd cd /root/copy m=`ls -l|awk '{print $5}'` n=$m while true ; do echo \"大小 $m and $n\" if [ $m -eq $n ] ; then echo \"OK!\" n=$m echo \"**********************************************\" echo \"size file01\" >> /tmp/ftp.cmd x=`ftp -nv < /tmp/ftp.cmd` echo \"--------------------------\" echo \"文件内容为:$x\" echo \"--------------------------\" m=`echo $x | awk '{print $31}'` echo \"--------------------------\" echo \"文件大小为:$m\" echo \"--------------------------\" else echo \"get `date +%Y`/`date +%Y`${x:0:2}/${y:0:2}/file01 /root/copy/file02\" >> /tmp/ftp1.cmd ftp -nv < /tmp/ftp1.cmd n=$m echo \"更新成功\" fi sleep 3 done 制作菜单脚本: 1) #!/bin/bash x=0 while [ $x -ne 5 ]; do echo \"List Directory......1\" echo \"Change Directory....2\" echo \"Edit File...........3\" echo \"Remove File.........4\" echo \"Exit Menu...........5\" echo \"Please choose one:\" read x case $x in 1)echo \"current directory is:\" ls `pwd`;; 2)echo \"Enter target directory:/\" echo \"List Directory......1\" echo \"Change Directory....2\" echo \"Edit File...........3\" echo \"Remove File.........4\" echo \"Exit Menu...........5\" echo \"Please choose one:\" read y case $y in 1)echo \"current directory is:\" ls `pwd`;; 2)echo \"Please a path:\" read z cd $z;; 3)echo \"Please input a file:\" read i vi $m;; 4)echo \"Please input a file\"; read j rm -rf $n;; 5)echo \"Exit\";; esac ;; 3)echo \"Please input a file:\" read m vi $m;; 4)echo \"Please input a file\"; read n rm -rf $n;; 5)echo \"Exit\"; esac done 2) #!/bin/bash x=1 while [ $x -ne 0 ]; do echo \"1.ls - list current directory\" echo \"2.cd - change directory\" echo \"3.mkdir - create a directory\" echo \"4.rm - remove\" echo \"0.quit\" echo please input: read x echo input:$x case $x in 1)echo \"ls - list current directory\";; 2)echo \"cd - change directory\";; 3)echo \"mkdir - create a directory\";; 4)echo \" 1.file - remove a file 2.directory - remove a directory\" read y echo input is:$y case $y in 1)echo \"file - create a directory\";; 2)echo \"directory - remove a directory\";; *)echo \"bad\";; esac ;; 0)echo \"bad\"; esac done 大量发邮件脚本: 1) #!/bin/bash exec 3 .... `date`\" >mymail#生成一封邮件 mail -S \"Happy New Year!\" $c < mymail done 3<&0- 2) #!/bin/bash exec 3 mail -S \"Happy New Year!\" $c < .... `date`\"#用临时文档( < #!/usr/bin/expect spawn ssh [lindex $argv 0] set password [lindex $argv 1] expect \"*password:\" send \"$password\\r\" expect eof interact #把控制权交给用户 大批量创建用户和修改密码: #此两脚本为我同学所写,觉得好就贴出来了 #!/bin/bash #此脚本适合于ubuntu下 #此小脚本为方便需要批量添加大量用户的管理员而写,密码默认设置为用户名. read -p \"请输入你想要添加的用户名和需要的个数(如:xuanfei 100):\" a b for((i=1;i<=$b;i++)) do useradd -m $a$i && echo \"$a$i:$a$i\" > swp && chpasswd < swp && pwconv && echo \"添加$a$i用户成功\" done rm -rf swp 2) #!/bin/bash #此脚本适合于Redhat下 for((i=0;i<10;i++)) do useradd user$i echo \"加用户 $user 成功\" echo \"user$i\" | passwd --stdin user$i done 一、构造字符串 直接构造 STR_ZERO=hello STR_FIRST=\"i am a string\" STR_SECOND='success' 重复多次 #repeat the first parm($1) by $2 times strRepeat() { local x=$2 if [ \"$x\" == \"\" ]; then x=0 fi local STR_TEMP=\"\" while [ $x -ge 1 ]; do STR_TEMP=`printf \"%s%s\" \"$STR_TEMP\" \"$1\"` x=`expr $x - 1` done echo $STR_TEMP } 举 例: STR_REPEAT=`strRepeat \"$USER_NAME\" 3` echo \"repeat = $STR_REPEAT\" 二、赋值与拷贝 直接赋值 与构造字符串一样 USER_NAME=terry 从 变量赋值 ALIASE_NAME=$USER_NAME 三、联接 直 接联接两个字符串 STR_TEMP=`printf \"%s%s\" \"$STR_ZERO\" \"$USER_NAME\"` 使用 printf可以进行更复杂的联接 四、求长 求字符数(char) COUNT_CHAR=`echo \"$STR_FIRST\" | wc -m` echo $COUNT_CHAR 求字节数(byte) COUNT_BYTE=`echo \"$STR_FIRST\" | wc -c` echo $COUNT_BYTE 求字数(word) COUNT_WORD=`echo \"$STR_FIRST\" | wc -w` echo $COUNT_WORD 计算字符串长度可用的三种方法: echo “$str”|awk '{print length($0)}' expr length “$str” echo “$str”|wc -c 但是第三种得出的值会多1,可能是把结束符也计算在内了 判断字符串为空的方法有三种: if [ \"$str\" = \"\" ] if [ x\"$str\" = x ] if [ -z \"$str\" ] 注意:都要代双引号,否则有些命令会报 错,养成好习惯吧! 五、比较 相等比较 str1 = str2 不 等比较 str1 != str2 举例: if [ \"$USER_NAME\" = \"terry\" ]; then echo \"I am terry\" fi 小于比较 #return 0 if the two string is equal, return 1 if $1 < $2, else 2strCompare() { local x=0 if [ \"$1\" != \"$2\" ]; then x=2 localTEMP=`printf \"%s\\n%s\" \"$1\" \"$2\"` local TEMP2=`(echo \"$1\"; echo \"$2\") |sort` if [ \"$TEMP\" = \"$TEMP2\" ]; then x=1 fi fi echo $x } 六、测试 判空 -z str 判 非空 -n str 是否为数字 # return 0 if the string is num, otherwise 1 strIsNum() { local RET=1 if [ -n \"$1\" ]; then local STR_TEMP=`echo \"$1\" | sed 's/[0-9]//g'` if [ -z \"$STR_TEMP\" ]; then RET=0 fi fi echo $RET } 举例: if [ -n \"$USER_NAME\" ]; then echo \"my name is NOT empty\" fi echo `strIsNum \"9980\"` 七、分 割 以符号+为准,将字符分割为左右两部分 使用sed 举例: 命令 date --rfc-3339 seconds 的输出为 2007-04-14 15:09:47+08:00 取其+左边的部分 date --rfc-3339 seconds | sed 's/+[0-9][0-9]:[0-9][0-9]//g' 输出为 2007-04-14 15:09:47 取+右边的部分 date --rfc-3339 seconds | sed 's/.*+//g' 输出为 08:00 以 空格为分割符的字符串分割 使用awk 举例: STR_FRUIT=\"Banana 0.89 100\" 取第3字段 echo $STR_FRUIT | awk '{ print $3; }' 八、子字符串 字 符串1是否为字符串2的子字符串 # return 0 is $1 is substring of $2, otherwise 1 strIsSubstring() { local x=1 case \"$2\" in *$1*) x=0;; esac echo $x } 一、 Linux shell 截取字符变量的前8位,有方法如下: 1.expr substr “$a” 1 8 2.echo $a|awk ‘{print substr(,1,8)}’ 3.echo $a|cut -c1-8 4.echo $ 5.expr $a : ‘\\(.\\\\).*’ 6.echo $a|dd bs=1 count=8 2>/dev/null 二、 按指定的字符串截取 1、第一种方法: ${varible##*string} 从左向右截取最后一个string后的字符串 ${varible#*string}从左向右截取第一个string后的字符串 ${varible%%string*}从右向左截取最后一个string后的字符串 ${varible%string*}从右向左截取第一个string后的字符串 “*”只是一个通配符可以不要 例 子: $ MYVAR=foodforthought.jpg $ echo ${MYVAR##*fo} rthought.jpg $ echo ${MYVAR#*fo} odforthought.jpg 2、第二种方法:${varible:n1:n2}:截 取变量varible从n1到n2之间的字符串。 可以根据特定字符偏移和长度,使用另一种形式的变量扩展,来选择特定子字符串。试着在 bash 中输入以下行: $ EXCLAIM=cowabunga $ echo ${EXCLAIM:0:3} cow $ echo ${EXCLAIM:3:7} abunga 这种形式的字符串截断非常简便,只需用冒号分开来指定起始字符和子字符串 长度。 三、按照指定要求分割: 比如获取后缀名 ls -al | cut -d “.” -f2 因篇幅问题不能全部显示,请点此查看更多更全内容