字符串操作符:
字符串操作符可以有一下的作用
1、确保变量的存在
2、设置变量的默认值
3、捕获未设置变量导致的错误
4、删除匹配模式的变量的值部分内容
语法:
${varname:-word}如果Varname存在且非null,返回其值,否则返回word。如果变量为定义,返回一
个默认值
${varname:=word}如果Varname存在且非null,返回其值,否则将其设置为word,然后返回其值。
位置参数和特殊参数不能这样设置。如果变量未定义,设置该变量为默认值
${varname:?message}如果Varname存在且非null,返回其值,否则打印message,并退出当前命
令或者脚本。用来捕获未定义的变量导致的错误。
${varname:+word}如果Varname存在且非null,返回word,否则返回null。测试一个变量的存在性
${varname::offset:length}返回$varname从offset开始长度为length的子字符串。$varname里
的第一个字符位置为0.
一、将数据文件排序,显示数值最高的N行,默认N等于10.假定下面是一个艺术家有多少签名的数据文件。文件内容如下:
5 Degh
2 Split
3 Minds
1 Antoni
脚本:
filename=$1
howmany=${2:-10}
sort -nr $filename | head -$howmany
解释:
sort的-n将每行的第一个单词解释为数字。-r表示逆序排列,就是降序排列。
${2:-10}用到了${varname:-word}
优化:
filename=${1:?"filename missing"}
加入第三个参数header,如果header的值不为null,则加入输出头ALBUM ARTIST。
header=$3
echo -e -n ${3:+"ALBUM ARTIST\n"}
echo的-n选项使其打印参数后不打印LINEFEED。因此如果header为null,此语句将不打印任何内容,及时空行都没有。否则将打印头行和LINEFEED(\n).-e选项使echo将\n解释为LINEFEED而非其字面意义。
优化后如下:
header=$3
echo -e -n ${header:+"ALBUM ARTIST\n"}
filename=${1:?"filename missing"}
howmany=${2:-10}
sort -nr $filename | head -$howmany
模式和模式匹配:
(也就是对变量里面的内容截头去尾????)
${variable#pattern} 如果模式匹配变量取值的开头,删除最短的匹配部分,并返回其余部分
${variable##pattern} 如果模式匹配变量取值的开头,删除最长的匹配部分,并返回其余部分
${variable%pattern}如果模式匹配变量取值的结尾,删除最短的匹配部分,并返回其余部分
${variable%%pattern}如果模式匹配变量取值的结尾,删除最常的匹配部分,并返回其余部分
${variable/pattern/string}
${variable//pattern/string}将variable中匹配模式最长部分替换为string。第一种格式中只有第一个匹配部分被替换,第二种中所有的匹配部分都会被替换。如果模式以#开头就必须匹配开头,反之,以%开头就必须匹配结尾。如果string为null就删除匹配的部分。如果varianle为@或者*,操作被一次应用于每个位置并且扩展为结果列表。
例子:
path="/home/cam/book/long.file.name"
表达式 结果
${path##/*/} long.file.name
${path#/*/} cam/book/long.file.name"
$path /home/cam/book/long.file.name
${path%.*} /home/cam/book/long.file
${path%%.*} /home/cam/book/long
/*/匹配两个斜线间的部分内容,.*匹配点号后面的内容
二、接收一个PCX文件,转换成GIF文件,过程的一部分就是修改文件名。
脚本:outfile=${filename%.pcx}.gif
三、去掉文件名的前缀
脚本:bannername=${pathname##/*/}
四、PATH打印出来时为一行,且目录之间用冒号分隔很难区分,所以改成一个目录对应一行。
脚本:echo -e ${PATH//:/'\n'}
命令替换:
也就是可以将命令的输出作为变量,语法:
$(UNIX command)
下面是简单实例:
$(pwd) 值为当前目录
$(ls $HOME) 为用户根目录下的所有文件
$(ls $(pwd) 为当前目录下的所有文件名
五、继续一的内容,假设是更大的数据列表,该列表由列或者域组成。每行有有名字,标题,年份等,用符号|分隔开。要处理列表中的单个列,域名需要不被转换成域编号。
下面就学习一下命令 cut
假设数据列表文件album,其内容如下:
Depeche|Speak and Spell|Mute|1981
Depeche|Great Reward|Mute|1984
Depeche|101|Mute|1981
Depeche|Violator|Mute|1981
下面是抽出第四列(年)额的命令:
cut -f4 -d\| album
-d参数指定域的分隔符为|,(tab为默认值)
-f表示域的编号
六、结合who命令,给当前登录的所有用户发送邮件。
who的输出如下:
knight tty7 2010-04-27 08:57 (:0)
knight pts/0 2010-04-27 08:57 (:0.0)
knight pts/1 2010-04-27 08:58 (:0.0)
knight pts/2 2010-04-27 17:22 (:0.0)
knight pts/3 2010-04-27 18:05 (:0.0)
各域由空格分隔,而不是tab。所以抽取第一个域:
who | cut -f1 -d' '
单引号里面是一个空格
后面直接:
mail $(who | cut -f1 -d' ')
七、结合ls和grep命令,列出最后修改日期为指定日期的文件。
先观察ls -l的文件布局。它依赖于开始于42列的日期和第55列的文件名。
所以命令如下:
ls -l | grep -i "^.\{42\}$date" | cut -c55-
命令中正则表达式的意思是,从行首开始匹配,匹配任意42个字符之后,也会是用点表示,接下来匹配date的值。cut命令也是一个亮点。之前那个问题学到的cut是按域来分列。这里用参数-c,表示事实在在的列,也就是一个字符一列,55-表示55列后的所有列。。。学习了。。。。。。
pushd和dpopd(这对函数已嵌入到bash)
函数pushd和popd实现了目录堆栈,使你可以暂时移动到别的目录,并让shell记住你以前的位置。
环境变量DIRSTACK储存了当前的目录。
一下为两个函数的最初版本:
pushd ()
{
dirname=$1
DIRSTACK="$dirname ${DIRSTACK:-$pwd' '}"
cd ${dirname:?"missing directory name."}
echo "$DIRSTACK"
}
popd ()
{
DIRSTACK=${DIRSTACK#* }
cd ${DIRSTACK%% *]
}
慢慢研究研究。。。。。
阅读(846) | 评论(0) | 转发(0) |