shell截取字符串shell截取字符串
shell截取字符串2010-07-30 10:20环境变量
在bash中定义环境变量的标准方法是:
$myvar='This is my environment variable~'
以上命令定义了一个名为"myvar"的环境变量,并包含字符串"This is my environment variable~"。以上有几点注意事项:第一,在等号"="的两边没有空格,任何空格将导致错误。第二个件要注意的事是:虽然在定义一个字时能够省略引号,但是当定义的环境变量值多于一个字时(包含空格或制表键),引...
shell截取字符串
shell截取字符串2010-07-30 10:20环境变量
在bash中定义环境变量的标准方法是:
$myvar='This is my environment variable~'
以上命令定义了一个名为"myvar"的环境变量,并包含字符串"This is my environment variable~"。以上有几点注意事项:第一,在等号"="的两边没有空格,任何空格将导致错误。第二个件要注意的事是:虽然在定义一个字时能够省略引号,但是当定义的环境变量值多于一个字时(包含空格或制
键),引号是必须的。第三,虽然通常能够用双引号来替代单引号,但在上例中,这样做会导致错误。因为使用单引号禁用了称为扩展的bash特性,其中,特别字符和字符系列由值替换。例如,"~"字符是历史扩展字符,bash通常将其替换为前面输入的命令。尽管这个类似于宏的功能很便利,但我们现在只想在环境变量后面加上一个简单的感叹号,而不是宏。
另一个例子
$echo foo$myvarbar bash会困惑,到底扩展$m、$my、$myvar、$myvarbar.在这种情况下要用显式的花括号将他括起。
$echo foo${myvar}bar
一定要记住:当环境变量没有用空白(空格或制表键)和周围文本分开时,要使用更明确的花括号形式。
当一个环境变量被导出时,他能够自动地由以后运行的任何脚本或可执行程式环境使用。shell脚本能够使用shell的内置环境变量支持"到达"环境变量,而C程式能够使用getenv()函数调用。如下C代码示例:
#include
#include int main(void){
char*myenvvar=getenv("myvar");
printf("The myvar environment variable is%s",myenvvar);
}
直接执行程式,结果为:
The myvar environment variable is(null) 在export myvar后,程式执行结果为:
The myvar environment variable is This is my environment variable~ 使用unset除去环境变量后,程式执行结果为:
The myvar environment variable is(null) 另外,也能够在一行定义并到处环境变量,如:
export myvar=abc
截断字符串概述
截断字符串是将初始字符串截断成较小的单独块,他是一般shell脚本每
天执行的任务之一。
$basename/usr/local/share/doc/foo/foo.txt foo.txt Basename是个截
断字符串的极简便工具。他的相关命令dirname返回basename丢弃的"另"一个
部分路径。
$dirname/usr/local/share/doc/foo/foo.txt /usr/local/share/doc/foo
命令替换
如何创建一个包含可执行命令结果的环境变量,能够通过如下方法: $MYDIR=`dirname/usr/local/share/doc/foo/foo.txt`
$echo$MYDIR
/usr/local/share/doc/foo
以上程式需要注意的是:在第一行,将要执行的命令以反引号括起。不是
标准的单引号,而是键盘中通常位于Tab键之上的单引号。(注:单引号中的内
容将会被强制显示,也就是说单引号中的命令不会被替换)
除了反引号``外,还能够使用$()来完成同样操作
$MYDIR=$(dirname/usr/local/share/doc/foo/foo.txt)
$echo$MYDIR
/usr/local/share/doc/foo
使用命令替换能够将任何命令或命令管道放在``或$()之间,并将其分配给
环境变量。
象专业人员那样截断字符串
有时候我们需要执行更高级的字符串"截断",如下例子: $MYVAR=foodforthought.jpg
$echo${MYVAR##*fo}
rthought.jpg
$echo${MYVAR#*fo}
odforthought.jpg
第一个echo,bash取得MYVAR,找到从字符串"foodforthought.jpg"开始处开始、且匹配通配符"*fo"的最长子字符串,然后将其从字符串的开始处截去。
第二个echo,bash取得MYVAR,找到从字符串"foodforthought.jpg"开始处开始、且匹配通配符"*fo"的最短子字符串,然后将其从字符串的开始处截去。
记忆方法:当搜索最长匹配时,使用##(因为##比#长)。当搜索最短匹配时,使用#。如何记住使用"#"字符来从字符串开始部分出去?在美国键盘上,shift-4是"$",他是bash变量扩展字符。在键盘上,紧靠"$"左边的是"#"。这样,能够看到:"#"位于"$"的"开始处",因此(根据我们的记忆法),"#"从字符串的开始处除去字符。同理,使用"%"来从尾部截去字符串:
$MYFOO="chickensoup.tar.gz"
$echo${MYFOO%%.*}
chickensoup
$echo${MYFOO%.*}
chickensoup.tar
假如忘记了应该使用"#"还是"%",则看一下键盘上的3、4和5键,然后猜出来。
更有另一种形式的变量扩展,来选择特定子字符串。
$EXCLAIM=cowabunga
$echo${EXCLAIM:0:3}//表示从下标0开始取3个
cow
$echo${EXCLAIM:3:7}//表示从下标3开始取7个
abunga
请注意命令替换$()和截断字符串${}的区别
应用字符串截断
下面是个简单的shell脚本,这个脚本接受一个文档作为自变量,然后打印:该文档是否是个tar文档。
#~/bin/bash if["${1##*.}"="tar"]
then echo This appears to be atarball.
else echo At first glance,this does not appear to be atarball.
fi
看一下上例使用的"if"语句。语句中使用了一个布尔表达式。在bash中,"="比较运算符检查字符串是否相等。在bash中,任何布尔表达式都用方括号括起。
(是传给脚本的第一个命令行自变量,是第二个,以此类推。)
If语句
if[condition]
then action fi
只有当condition为真时,该语句才执行操作,否则不执行操作,并继续执行"fi"之后的语句。
if[condition]
then action elif[condition2]
then action2
.
.
.
elif[condition3]
then else actionx fi
以上"elif"形式将连续测试每个条件,并执行符合第一个真条件的操作。假如没有条件为真,则将执行"else"操作,假如有一个条件为真,则继续执行整个"if,elif,else"语句之后的行。
Bash编程实例二
在前一篇bash的介绍性文章中,我们了解了脚本语言的一些基本元素和使用bash的原因。在本文(即第二部分)中,将继续前一篇的内容,并讲解条件
then)语句、循环和更多的bash基本结构。 (if-
Bash编程实例
第二部分
接收自变量
看一下如下的例子:
#~/bin/bash echo name of script.is[message] echo first argument
is echo second argument is echo seventeenth argument is echo number
of arguments is$#
Bash中将"[message]"扩展成从命令行调用的脚本名称,"$#"被扩展成传递给脚本的自变量数目。(请注意$和0是连起来的)
在Bash编程中有时候需要一次引用任何命令行自变量,针对这种用途,bash实现了变量"$@",他被扩展成任何用空格分开的命令行参数。
Bash编程结构
在各种编程语言中出现的"if"语句和"for"循环等标准编程结构,Bash有自己的版本。以下几节,将介绍几种bash结构,并演示这些结构及其和其他编程语言中结构的差异。
方便的条件语句
在C语言中,要比较特定文档是否比另一个文档新必须使用两个stat()调用和两个stat结构来进行手工比较。而在bash中,因为其内置了标准文档比较运算符,因此,确定"/tmp/myfile是否可读"和查看"$myvar是否大于4"相同容易。看下面的例子:
if[-z"$myvar"]
then echo"myvar is not defined"
fi
上例表示假如$myvar没有定义(即$myvar为0),则echo"."
bash中可使用的比较运算符如下:
运算符描述示例
文档比较运算符
-e filename假如filename存在,则为真[-e/var/log/syslog]
-d filename假如filename为目录,则为真[-d/tmp/mydir]
-f filename假如filename为常规文档,则为真[-f/usr/bin/grep]
-L filename假如filename为符号链接,则为真[-L/usr/bin/grep]
-r filename假如filename可读,则为真[-r/var/log/syslog]
-w filename假如filename可写,则为真[-w/var/mytmp.txt]
-x filename假如filename可执行,则为真[-L/usr/bin/grep]
filename1-nt filename2假如filename1比filename2新,则为真
[/tmp/install/etc/services-nt/etc/services]
filename1-ot filename2假如filename1比filename2旧,则为真
[/boot/bzImage-ot arch/i386/boot/bzImage]
字符串比较运算符(请注意引号的使用,这是防止空格扰乱代码的好方法)
-z string假如string长度为零,则为真[-z"$myvar"]
-n string假如string长度非零,则为真[-n"$myvar"]
string1=string2假如string1和string2相同,则为真["$myvar"="one two three"]
string1~=string2假如string1和string2不同,则为真["$myvar"~="one two three"]
算术比较运算符
num1-eq num2等于[3-eq$mynum]
num1-ne num2不等于[3-ne$mynum]
num1-lt num2小于[3-lt$mynum]
num1-le num2小于或等于[3-le$mynum]
num1-gt num2大于[3-gt$mynum]
num1-ge num2大于或等于[3-ge$mynum]
有时,有几种不同方法来进行特定比较。如下:
if["$myvar"-eq 3]
then echo"myvar equals 3"
fi if["$myvar"="3"]
then echo"myvar equals 3"
fi
上面两个比较执行相同的功能,但是第一个使用算术比较运算符,而第二个使用字符串比较运算符。
字符串比较说明
大多数时候,虽然能够不使用括起字符串和字符串变量的双引号,但这并不是好主意。因为假如环境变量中恰巧有一个空格或制表键,bash将无法分辨,从而无法正常工作。这里有一个错误的比较示例:
if[$myvar="foo bar oni"]
then echo"yes"
fi
在上例中,假如myvar等于"foo",则代码将按预想工作,不进行打印。但是,假如myvar等于"foo bar oni",则代码将因以下错误失败:
[:too many arguments
在这种情况下,"$myvar"(等于"foo bar oni")中的空格迷惑了bash。bash扩展"$myvar"之后,代码如下:
[foo bar ni="foo bar oni"]
因为环境变量没放在双引号中,所以bash认为方括号中的自变量过多。能够用双引号将字符串自变量括起来消除该问
。请记住,假如养成将任何字符串自变量用双引号括起的习惯,将除去很多类似的编程错误。"foo bar oni"比较应该写成:
if["$myvar"="foo bar oni"]
then echo"yes"
fi
注意:假如想引用在调用环境变量的时候最好使用""将环境变量括起来。(
环境变量的值,则不要使用单引号,因为单引号会禁用变量(和历史)扩展。如在上例中会只接受空格以前的字符)
循环结构:"for"
OK,开始我们的for循环了:)先看一个简单的例子:
#~/bin/bash for xin one two three four do echo number$x done
输出:
number one number two number three number four
这个例子中"for x"部分定义了一个名为"$x"的新环境变量(也称为循环控制变量),他的值被依次配置为"one"、"two"、"three"和"four"。每一次赋值之后,执行一次循环体("do"和"done"之间的代码)。在循环体内,象其他环境变量相同,使用标准的变量扩展语法来引用循环控制变量"$x"。还要注意,"for"循环总是接受"in"语句之后的某种类型的字列表。在这个例子中,指定了四个英语字母,但是字列表也能够引用磁盘上的文档,甚至文档通配符。再看一个使用标准shell通配符的例子:
#~/bin/bash for myfile in/etc/r*
do if[-d"$myfile"]
then echo"$myfile(dir)"
else echo"$myfile"
fi done
输出:
/etc/rc.d(dir)
/etc/resolv.conf
/etc/resolv.conf~
/etc/rpc
以上代码列出在/etc中每个以"r"开头的文档。要做到这点,bash在执行
,然后扩展他,用字符串循环之前首先取得通配符/etc/r*
/etc/rc.d/etc/resolv.conf/etc/resolv.conf~/etc/rpc替换。(也即循环语句被替换成for myfile
in/etc/rc.d/etc/resolv.conf/etc/resolv.conf~/etc/rpc)一旦进入循环,根据myfile是否为目录,"-d"条件运算符用来执行两个不同操作。假如是目录,则将"(dir)"附加到输出行。
还能够在字列表中使用多个通配符、甚至是环境变量:
for xin/etc/r--?/var/lo*/home/drobbins/mystuff/*/tmp/${MYPATH}/*
do cp$x/mnt/mydir done
虽然任何通配符扩展示例使用了绝对路径,但也能够使用相对路径,如下所示:
for xin./*mystuff/*
do echo$x is asilly file done
再看个例子:
for xin/var/log/*
do echo`basename$x`is afile living in/var/log done
看看如何使用"$@"的:
#~/usr/bin/env bash for thing in"$@" do echo you typed${thing}.
done
输出:
$allargs hello there you silly you typed hello.
you typed there.
you typed you.
you typed silly.
Shell算术
在学习另一类型的循环结构之前,最好先熟悉如何执行shell算术。能够
使用shell结构来执行简单的整数运算。只需将特定的算术表达式用"$(("和
"))"括起,bash就能够计算表达式。这里有一些例子:
$echo$((100/3))
33
$myvar="56"
$echo$(($myvar+12))
68
$echo$(($myvar-$myvar))
0$myvar=$(($myvar+1))
$echo$myvar 57
更多的循环结构:"while"和"until"
只要特定条件为真,"while"语句就会执行,其格式如下: while[condition]
do statements done
通常使用"While"语句来循环一定次数,比如,下例将循环10次: myvar=0 while[$myvar-ne 10] do echo$myvar myvar=$(($myvar+1)) done
能够看到,上例使用了算术表达式来使条件最终为假,并导致循环终止。 "Until"语句提供了和"while"语句相反的功能:只要特定条件为假,他们
就重复。下面是个和前面的"while"循环具备同等功能的"until"循环: myvar=0 until[$myvar-eq 10] do echo$myvar myvar=$(($myvar+1)) done Case语句
Case语句是另一种便利的条件结构。这里有一个示例片段: case"${x##*.}"in gz)
gzunpack${SROOT}/${x}
;;
bz2)
bz2unpack${SROOT}/${x}
;;
*)
echo"Archive format not recognized."
exit
;;
esac
在上例中,bash首先扩展"${x##*.}"。在代码中,"$x"是文档的名称,"${x##.*}"除去文档中最后句点后文本之外的任何文本。然后,bash将产生的字符串和")"左边列出的值做比较。在本例中,"${x##.*}"先和"gz"比较,然后是"bz2",最后是"*"。假如"${x##.*}"和这些字符串或模式中的任何一个匹配,则执行紧接")"之后的行,直到";;"为止,然后bash继续执行结束符"esac"之后的行。假如不匹配任何模式或字符串,则不执行任何代码行,在这个特别的代码片段中,至少要执行一个代码块,因为任何不和"gz"或"bz2"匹配的字符串都将和"*"模式匹配。
函数和名称空间
在bash中也能够定义函数。函数甚至能够使用和脚本接受命令行自变量类似的方式来接受自变量。
tarview(){
echo-n"Displaying contents of"
if[${1##*.}=tar]
then echo"(uncompressed tar)"
tar tvf elif[${1##*.}=gz]
then echo"(gzip-compressed tar)"
tar tzvf elif[${1##*.}=bz2]
then echo"(bzip2-compressed tar)"
|bzip2-d|tar tvf- cat
fi
}
(echo-n不换行)
上面定义了一个名为"tarview"的函数,他接收一个自变量,即某种类型的
tar文档。在执行该函数时,他确定自变量是哪种tar文档类型(未压缩的、
gzip压缩的或bzip2压缩的),打印一行信息性消息,然后显示tar文档的内
容。
$tarview shorten.tar.gz Displaying contents of shorten.tar.gz(gzip-compressed tar)
drwxr-xr-x ajr/abbot 01999-02-27 16:17 shorten-2.3a/
-rw-r--r--ajr/abbot 1143 1997-09-04 04:06 shorten-2.3a/Makefile
-rw-r--r--ajr/abbot 1199 1996-02-04 12:24 shorten-2.3a/INSTALL
-rw-r--r--ajr/abbot 839 1996-05-29 00:19 shorten-2.3a/LICENSE
.
名称空间
经常需要在函数中创建环境变量。虽然有可能,但是更有一个技术细节应
该了解。在大多数编译语言(如C)中,当在函数内部创建变量时,变量被放置
在单独的局部名称空间中。因此,假如在C中定义一个名为myfunction的函数,
并在该函数中定义一个名为"x"的自变量,则任何名为"x"的全局变量(函数之外的变量)将不受他的印象,从而消除了负作用。
在C中是这样,但在bash中却不是。在bash中,每当在函数内部创建环境变量,就将其添加到全局名称空间。这意味着,该变量将重写函数之外的全局变量,并在函数退出之后继续存在:
#~/usr/bin/env bash myvar="hello"
myfunc(){
myvar="one two three"
for xin$myvar do echo$x done
}
myfunc echo$myvar$x
运行此脚本时,他将输出"one two three three",这显示了在函数中定义的"$myvar"如何影响全局变量"$myvar",连同循环控制变量"$x"如何在函数退出之后继续存在(假如"$x"全局变量存在,也将受到影响)。
在这个简单的例子中,很容易找到该错误,并通过使用其他变量名来改正错误。但这不是正确的方法,解决此问题的最好方法是通过使用"local"命令,在一开始就预防影响全局变量的可能性。当使用"local"在函数内部创建变量时,将把他们放在局部名称空间中,并且不会影响任何全局变量。这里演示了如何实现上述代码,以便不重写全局变量:
#~/usr/bin/env bash myvar="hello"
myfunc(){
local x
local myvar="one two three"
for xin$myvar do echo$x done
}
myfunc echo$myvar$x
不重写全局变量"$myvar","$x"在myfunc之外不此函数将输出"hello"--
继续存在。在函数的第一行,我们创建了以后要使用的局部变量x,而在第二个例子(local myvar="one two three"")中,我们创建了局部变量myvar,同时为其赋值。在将循环控制变量定义为局部变量时,使用第一种形式很方便,因为不允许说:"for local xin$myvar"。此函数不影响任何全局变量,鼓励您用这种方式
任何的函数。只有在明确希望要修改全局变量时,才不应该使用"local"。创建局部环境变量时最好使用"local"。
特别声明:
1:资料来源于互联网,版权归属原作者
2:资料内容属于网络意见,与本账号立场无关
3:如有侵权,请告知,立即删除。
本文档为【shell截取字符串】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑,
图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。
本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。
网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。