Linux shell 命令和正则表达式

今天在Fedora20系统上编译VPP项目时遇到了一个问题,在最终编译并且使用rpmbuild生成的rpm安装包不正确,我们需要对生成rpm包的spec文件做一些小的修改。

首先我们来看看VPP自带的生成rpm包的spec描述文件,该文件为${VPP_TOPDIR}/build-root/rpm/vpp.spec, 我们可以打开看看该文件的内容:

其中在%install 段里面有如下的命令

1 #

2 # libraries
 3 #
 4 mkdir -p -m755 %{buildroot}%{_libdir}
 5 for file in $(find %{_vpp_install_dir}/*/lib* -type f -name ‘*.so.*.*.*‘ -print )
 6 do
 7     install -p -m 755 $file %{buildroot}%{_libdir}
 8 done
 9 for file in $(cd %{buildroot}%{_libdir} && find . -type f -print | sed -e ‘s/^\.\///‘)
10 do
11     # make lib symlinks
12     ( cd %{buildroot}%{_libdir} && 
13           ln -fs $file $(echo $file | sed -e ‘s/\(\.so\.[0-9]\+\).*/\1/‘) )
14 done

这里首先在%{buildroot}目录里面创建lib目录,然后调用install命令将编译出来的所有的VPP项目的lib文件拷贝到%{buildroot}目录里面的lib目录里面。

现在我们来看9~14行的一个 for循环命令,该命令主要是完成这样的一个功能:将%{buildroot}目录里面的lib目录里面的所有的库文件建立一个软链接文件。

比如:假如现在在%{buildroot}目录里面的lib目录里面有一个库文件libvnet.so.18.0.0, 那么上述for循环完成之后就在同一目录下建立了一个软链接文件libvnet.so.18并指向libvnet.so.18.0.0库文件。

现在我们来一步步的分析上面的9~14行的这个for循环语句的工作过程,我们假设在/usr/lib64/目录下有2个库文件,一个是libvpp.so.0.0.0, 一个是libvnet.so.18.0.0.

首先我们来看第9行的for语句后面的一个shell命令:

$(cd %{buildroot}%{_libdir} && find . -type f -print | sed -e ‘s/^\.\///‘)

那么等价于执行下面的一条命令:

$(cd /usr/lib64/ && find . -type f -print | sed -e ‘s/^\.\///‘)

这条命令是两条命令组合而成,首先执行cd /usr/lib64/切换工作目录到/usr/lib64/目录下,然后执行后续的find命令。

随后执行 find . -type f -print 命令的结果如下:

./libvpp.so.0.0.0

./libvnet.so.18.0.0

这里find命令的查找输出结果前面都带有路径的。然后将find命令查找的输出结果通过管道重定向到sed命令中,再来分析后面的sed命令。

sed -e ‘s/^\.\///‘:   查找行首以./开头的行并将./替换为空, 这里^表示匹配行首, 后面有两个转义符分别转义"点(.)"和"斜杠(/)",  s动作表示查找替换

那么经过sed命令处理之后的find查找结果就变为如下的结果了:

find . -type f -print | sed -e ‘s/^\.\///‘    经过sed处理后的find查找结果全部去掉了前面的路径了,该命令最终结果如下了:

libvpp.so.0.0.0

libvnet.so.18.0.0

至此,for循环中的file变量值就有了,file变量的值是集合{libvpp.so.0.0.0, libvnet.so.18.0.0}了。

下面我们再来分析for循环中的循环体语句。

( cd %{buildroot}%{_libdir} && ln -fs $file $(echo $file | sed -e ‘s/\(\.so\.[0-9]\+\).*/\1/‘) )

我们可以在现在举的这个例子里面将上面的命令进行替换展开:

( cd /usr/lib64/ && ln -fs libvpp.so.0.0.0 $(echo libvpp.so.0.0.0 | sed -e ‘s/\(\.so\.[0-9]\+\).*/\1/‘) )

( cd /usr/lib64/ && ln -fs libvnet.so.18.0.0 $(echo libvnet.so.18.0.0 | sed -e ‘s/\(\.so\.[0-9]\+\).*/\1/‘) )

我们具体来分析其中的sed命令,这里有一个正则表达式我们假设将正则表达式展开,那么得到如下的一个sed命令:

$(echo libvpp.so.0.0.0 | sed -e ‘s/(.so.[0-9]+).*/\1/‘)

注意:上述sed命令的正则表达式没有加转义字符啊。

(.so.[0-9]+).*     // (...)表示匹配子串并保存匹配的字符,[0-9]表示匹配1个数字字符,[0-9]+表示匹配1个或者多个数字字符,.表示匹配一个非换行符的任意字符,*表示匹配0个或者多个字符

\1//表示在这里直接引用前面查找匹配子串时保存的匹配字符

经过上面的分析,我们可以得出下面的shell命令运行的结果:

$(echo libvpp.so.0.0.0 | sed -e ‘s/(.so.[0-9]+).*/\1/‘)           //得到的结果字符串是: libvpp.so.0

$(echo libvnet.so.18.0.0 | sed -e ‘s/\(\.so\.[0-9]\+\).*/\1/‘) //得到的结果字符串是:libvnet.so.18

然后调用的ln -sf命令直接就创建了2个软链接文件:

libvpp.so.0-------->libvpp.so.0.0.0

libvnet.so.18--------->libvnet.so.18.0.0

虽然上面的shell命令创建了2个软链接文件,但是我们知道在Linux下程序引用动态链接库文件的时候一般习惯性使用-lvpp, -lvnet等来指定,这样一来依赖的库文件形式就是libvpp.so和libvnet.so了,而不是libvpp.so.0和libvnet.so.18了。

因此我们还需要创建2个软链接文件libvpp.so和libvnet.so, 也分别软链接到libvpp.so.0.0.0和libvnet.so.18.0.0。

我们只需要将上面的for循环修改一下即可,我们修改如下:

for file in $(cd %{buildroot}%{_libdir} && find . -type f -print | sed -e ‘s/^\.\///‘)

do

# make lib symlinks

( cd %{buildroot}%{_libdir} &&

ln -fs $file $(echo $file | sed -e ‘s/\(\.so\.[0-9]\+\).*/\1/‘)  &&
ln -sf $file $(echo $file | sed -e ‘s/\(\.so\).*/\1/‘) )

done

这样在for循环执行完之后,就在/usr/lib64目录里面分别创建了4个软链接文件了,其关系如下:

libvpp.so-------->libvpp.so.0.0.0

libvpp.so.0-------->libvpp.so.0.0.0

libvnet.so--------->libvnet.so.18.0.0

libvnet.so.18-------->libvnet.so.18.0.0

具体的关于sed命令的使用和正则表达式的详细说明,请参考如下的links:

http://man.linuxde.net/sed

http://www.infoq.com/cn/news/2011/07/regular-expressions-6-POSIX

时间: 2024-10-09 19:55:19

Linux shell 命令和正则表达式的相关文章

37条常用Linux Shell命令组合

序号 任务 命令组合 1 删除0字节文件 find . -type f -size 0 -exec rm -rf {} \; find . type f -size 0 -delete 2 查看进程,按内存从大到小排列 ps -e -o “%C : %p : %z : %a”|sort -k5 -nr 3 按cpu利用率从大到小排列 ps -e -o “%C : %p : %z : %a”|sort -nr 4 打印说cache里的URL grep -r -a jpg /data/cache/*

常用Linux Shell命令组合

序号 任务 命令组合 1 删除0字节文件 find . -type f -size 0 -exec rm -rf {} \;find . type f -size 0 -delete 2 查看进程,按内存从大到小排列 ps -e -o “%C : %p : %z : %a”|sort -k5 -nr 3 按cpu利用率从大到小排列 ps -e -o “%C : %p : %z : %a”|sort -nr 4 打印说cache里的URL grep -r -a jpg /data/cache/*

linux shell 命令学习(5) xxd- make a hexdump or do the reverse.

对于标准输入或者给定的文件,显示其16进制的内容.也可以反过来进行转换. ? 1 2 3 xxd -h[elp] xxd [options] [infile [outfile]] xxd -r[evert] [options] [infile [outfile]] 如果没有指定输入文件, 则采用标准输入. -b: 以2进制格式进行输出 ? 1 2 3 4 [[email protected] src]$ xxd -b train.ini 0000000: 01011011 01110100 01

[Python] 利用commands模块执行Linux shell命令

用Python写运维脚本时,经常需要执行linux shell的命令,Python中的commands模块专门用于调用Linux shell命令,并返回状态和结果,下面是commands模块的3个主要函数: 1. commands.getoutput('shell command') 执行shell命令,返回结果(string类型) >>> commands.getoutput('pwd') '/home/oracle' 2. commands.getstatus('file') 该函数

linux shell 命令

linux shell 命令 什么是Shell? Shell 是连接操作系统内核 与 用户 的接口. 终端是shell的表现形式. 什么是Shell编程? Shell 脚本语言加上linux 命令语句就构成了shell程序.优点在于批量处理.不用用户每次手动输入. bash是shell程序解释器的一种. 常用命令 pwd:print working directory,打印工作目录. cd:chang directory,改变工作目录. 可使用绝对命令或相对命令. ls:list,查看目录内容.

[Shell&Mac&Environment variables]自己常用的Mac(或者说Linux)Shell命令小结,含Mac使用zsh shell的环境变量的有关配置方法

今天在使用tomcat的配置的时候,我用的mac,要是用到一些命令去配置tomcat. 问题来了: 我每次要去启动tomcat服务特别麻烦,因为我要先进入tomcat所在的文件目录,或者不进入使用~/,但是因为我把tomcat放到了一个比较“深“的文件夹里,所以命令显得又丑又长. 问题解决方案: 1.使用环境变量(修改.bashrc的方法) a.先查看自己的Mac目前正在用的是什么shell echo $SHELL 返回结果类似如下图 这里我是zsh,,也许你是bash,不过没关系,配置环境变量

java执行linux shell命令,并拿到返回值

1 package com.suning.spc.util; 2 3 import java.io.IOException; 4 import java.io.InputStream; 5 import java.nio.charset.Charset; 6 7 import org.slf4j.Logger; 8 import org.slf4j.LoggerFactory; 9 10 import ch.ethz.ssh2.ChannelCondition; 11 import ch.eth

使用Runtime.exec()运行windwos dos或linux shell命令

使用Runtime.exec()运行windwos dos或linux shell命令,按实际情况具体测试 实例代码: package com.bookoo.test.command; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter

Linux shell命令 cp 加上-f还是提示是否覆盖

这是因为环境变量中有 allias cp='cp -i' 为了去掉这个系统自带的别名,可以使用grep -r --include="*" "alias cp"  /查找设置这个环境变量的脚本文件: 我的ubuntu机器上是: ./.bash_aliases:alias cp='cp -i' 于是我将./.bash_aliases文件中的这句话去掉即可 然后使用 source ./.bash_aliases 使其立即生效 2014年7月5日11:49:54 www.u