不是系统的学习,只是学习一下常用的命令,理解可能有错误,如果有路过的大神能够补充和指正,万分感谢!
1.根据文件名查找文件
1.1利用find命令
find [path] -type f -name '[filename]' ! -path "[excludepath]"
在path
目录及子目录中寻找名字为filename
的文件,并打印。[path]为空的时候查找当前目录及当前目录子目录下所有名字为filename的文件,忽略excludepath
目录及其子目录下的结果。例如:
//查找当前目录及子目录下的所有.sh文件并打印
$ find . -name '*.sh'
//查找catkin_ws目录及子目录下所有名为‘main.cpp’的文件并打印
$ find ~/catkin_ws -name 'main.cpp'
查找catkin_ws目录及子目录下所有名为‘main.cpp’的文件并打印
1.2利用grep命令
有空总结
2.文件内容查找和替换
https://blog.csdn.net/xiexingshishu/article/details/50514132
2.1 文件内容查找
2.1.1利用sed命令
sed -n '/[text]/p' [filename]
在filename
文件中查找text
并将所在行打印出来。
例如:
//在当前目录下asdf.aaa文件中查找'ff'字符串并打印所在行
$ sed -n '/ff/p' ./asdf.aaa
asdfasdff
ff1
2.1.2利用grep命令
grep查找文件内容指南有空再总结
grep [text] [filename]
在filename
中查找text
并打印,例如
//在aaa.aaa文件中查找aaa并打印所在行
grep aaa aaa.aaa
//在aaa.aaa文件中查找aaa(忽略大小写)并打印所在行
grep -i 5 Aaa aaa.aaa
//打印本行及以下5行
grep -A 5 aaa aaa.aaa
//打印本行及以上5行
grep -B 5 aaa aaa.aaa
//打印本行及上下5行
grep -C 5 aaa aaa.aaa
2.2 文件内容替换
sed -i 's/[old]/[new]/g' [filename]
在filename
文件中查找old
字符串并将其替换为new
字符串
例如:
//将asdf.aaa中的ff替换为gg
$ sed -i 's/ff/gg/g' asdf.aaa
//在asdf.aa中查找ff,无结果
$ sed -n '/ff/p' asdf.aaa
//在asdf.aaa中查找gg,发现2.1中两行中的ff已经变成gg
$ sed -n '/gg/p' asdf.aaa
asdfasdgg
gg1
3.在指定文件中查找内容和替换
结合上文中提到的文件名查找和文件内容查找和替换,通过管道符|
和xargs
(可以将管道数据转换成命令行参数)命令,将find命令的输出作为sed的命令行参数,完成指定文件中内容查找和替换的工作。
find [path] -name '[filename]' | xargs sed -n '[text]'
在path
下查找filename
文件,并在这些文件中查找包含text
的行并打印
find [path] -name '[filename]' | xargs sed -i 's/[old]/[new]/g'
在path
下查找filename
文件,并将这些文件中old
的字符串替换为new
提示:/
等符号需要转义符
例如:
//查找当前目录及子目录中的.launch文件,并将其中包含/robots/字符串的行打印出来
find . -name '*.launch' | xargs sed -n '/\/robots\//p'
//查找当前目录及子目录中的.launch文件,并将其中包含/robots/的字符串替换为/urdf/
find . -name '*.launch' | xargs sed -i 's/\/robots\//\/urdf\//g'
4.将内容另一个文件的指定行后面
4.1 直接插入
sed -i '/[insert_position]/a[insert_text]' [filename]
将insert_text
插入到filename
文件中insert_position
的下一行,其中插入到下一行是由/a
决定的,/a
后面再加一个反斜杠\
好像也没什么影响,但是看起来能清楚一些。秉持着能用就行的态度,不去追究太深。如果要插入多行的文字,就在换行时加个\n
就好。举个栗子:
//在aaa.aaa文件中的aaa111所在行的下一行插入bbb222和ccc333
sed -i '/aaa111/abbb222\nccc333' aaa.aaa
4.2 将文件内容插入另一个文件的指定行后面
这里多说两句,这个问题的实际应用场景就是同事用Solidworks导出的URDF模型需要仿真,我需要将一些模型插入他的urdf里,上面4.1的方法就很麻烦了。
sed -i '[行号]r 内容所在的文件' [要被插入内容的文件]
例如:
//讲bbb.bbb的内容插入在aaa.aaa的第三行后面
sed -i '3r bbb.bbb' aaa.aaa
5.实现if判断执行
5.1 if的语法
//一般模式
if [ condition ]; then
//command
fi
注意在[
后面和]
前面都必须要有空格,其他注意事项见上面的链接
5.2实现根据文本内容是否存在判断是否执行插入文本命令
这里承接4中的文件文本插入,需要先判断之前是否插入过,如果已经执行过插入文本的操作就不要再次执行。因为sed和awk命令无论是否检索到要求的值,返回值都为0,所以命令不能够作为逻辑判断的条件,遂使用2.1.2中的grep命令。
grep命令返回值:0成功,1规则未找到,2文件未找到
可使用#?
获取上一条命令的返回值,作为判断条件
例如:
#[ INT1 -eq INT2 ] INT1和INT2两数相等返回为真 ,=
#[ INT1 -ne INT2 ] INT1和INT2两数不等返回为真 ,<>
grep aaa111 aaa.aaa
#判断上一条的返回值是否为0
if [ $? -eq 0 ]; then
echo "aaa111 found"
fi
最后完成任务的成品脚本为
#!/bin/sh
#设定变量var=elevator11
var='elevator11'
#进入目录
cd ~/catkin_ws/src/$var
#在.launch文件中查找'/robots'并替换为'/urdf/'
find . -name '*.launch' | xargs sed -i 's/\/robots\//\/urdf\//g'
#在package.xml文件中查找'me2email'并替换为'me@email'
find . -name 'package.xml' | xargs sed -i 's/me2email/me@email/g'
#在.launch文件中查找'elevator11/urdf.rviz'替换为'/home/xcy/tree.rviz'
find . -name '*.launch' | xargs sed -i 's/$(find "$var")\/urdf.rviz/\/home\/xcy\/tree.rviz/g'
#在elevator11.urdf中查找字符串'world'
grep world urdf/$var.urdf
#如果不存在,则插入文件中的内容
if [ $? -ne 0 ]; then
sed -i '2r /home/xcy/world.urdf' urdf/$var.urdf
fi