[Linux Shell学习系列十四]sed和awk-4.sed与Shell
D29
本节学习如何在sed中使用Shell变量和如何通过sed的输出设置Shell变量。
1. 在sed中使用Shell变量
Shell中环境变量以美元符号$开头,如$PATH、$var、$i;
sed中$用于指示输入文件的最后一行,或是行的末尾(在LHS中),或是字面意义的符号(在RHS中)。
注:LHS和RHS分别指sed指令的左侧部分和右侧部分,如替换编辑命令's/LHS/RHS'。
sed不能直接访问Shell中的变量,必须使用双引号来扩展Shell的变量。
#示例文件 $ cat input.file The name of terminal which you are using is _terminal-type_. #环境变量TERM的值 $ echo $TERM vt100 #如果sed命令使用单引号,则不能访问变量 $ sed 's/_terminal-type_/$TERM/g' input.file The name of terminal which you are using is $TERM. #必须使用双引号访问变量 $ sed "s/_terminal-type_/$TERM/g" input.file The name of terminal which you are using is vt100.
当在sed指令中使用的模式是一个Shell变量时,它可能会是任意字符串。比如变量中包含了sed指令的界定符/。因此建议使用其他不会引起冲突的字符作为界定符。(对/进行转义也可以,但麻烦)
1)移除文件中的空白行
$ cat removeBlankLines.sh #!/bin/bash #202006 if [ -z "$1" ] then echo "Usage: `basename $0` target-file" exit 1 fi
#-e选项表示后跟一个编辑命令(此处可省略)
#^$匹配空行
#d是删除命令
#注意该命令不会修改目标文件,如果需要修改,需加入-i选项 sed -e "/^$/d" "$1" exit 0
2)替换文件中的字符串
$ cat substituteStr.sh #!/bin/bash #202006 ARGS=3 if [ $# -ne "$ARGS" ] then echo "Usage: `basename $0` old-pattern new-pattern filename" exit 2 fi old_pattern=$1 new_pattern=$2 if [ -f "$3" ] then file_name=$3 else echo "File \"$3\" does not exist." exit 3 fi #-e表示后跟编辑命令 #s是替换命令 #使用#作为界定符 #g选项指示替换一行中所有匹配old_pattern的字符串 sed -e "s#$old_pattern#$new_pattern#g" $file_name exit 0
3)检查目录中所有二进制文件的来源
$ cat checkAuthorship.sh #!/bin/bash #202006 if [ -z "$1" ] then echo "Usage: `basename $0` target-dir" exit 2 fi if [ -d "$1" ] then directory="$1" else echo "Directory \"$1\" does not exist." exit 3 fi fstring="Free software foundation" #for循环遍历指定目录下所有文件 for file in `find $directory -type f -name '*' | sort` do #strings 命令在对象文件或二进制文件中查找可打印的字符串 #-f选项在显示字符串前先显示文件名 #sed命令在输出时替换掉strings命令输出的文件名中的路径 strings -f $file | grep "$fstring" | sed -e "s#$directory##" done exit 0
输出示例:
$ ./checkAuthorship.sh ~/20200511study/ testSubStr.txt: Free software foundation
4)格式化邮件内容
$ cat formatEmail.sh #!/bin/bash #202006 E_BADARGS=65 E_NOFILE=66 if [ -z "$1" ] then echo "Usage: `basename $0` filename" exit $E_BADARGS fi if [ -f "$1" ] then filename="$1" else echo "File \"$1\" does not exist." exit $E_NOFILE fi MAXWIDTH=70 #sed脚本保存到变量中 #s表示替换命令 #替换以>、空格、制表符开头的行 sedscript='s/^>// s/^ *>// s/^ *// s/ *// ' #执行sed脚本,然后用fold命令将每行的长度折叠成最大$MAXWIDTH个字符 sed "$sedscript" $1 | fold -s --width=$MAXWIDTH exit 0
示例:
#初始文件 $ cat testemail.txt <testemail> >aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa >b c aaaa> bbbb> ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc dddd #执行 $ ./formatEmail.sh testemail.txt <testemail> aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaa b c aaaa> bbbb> cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc c dddd
2. 从sed输出中设置Shell变量
1)批量修改文件名
$ cat rename.sh #!/bin/bash #202006 ARGS=2 ONE=1 if [ $# -ne "$ARGS" ] then echo "Usage: `basename $0` old-pattern new-pattern" exit 2 fi number=0 for filename in *$1* do if [ -f "$filename" ] then #去除文件路径 fname=`basename "$filename"` #替换文件名中字符串,形成新的文件名 newname=`echo $fname | sed -e "s/$1/$2/g"` #将文件重命名 mv "$fname" "$newname" #计数 let "number += 1" fi done if [ "$number" -eq "$ONE" ] then echo "$number file renamed/" else echo "$number files renamed" fi exit 0
示例:
#替换前 $ ls -f | grep "Test" Test.tar.bz2 rmTest.sh Testdebugtrap.sh Testemail.txt Test.tar Testfile TestSubStr.txt subshell_Test.sh Testtrapexit.sh Test.tar.gz sedTestReadFile Testtrapsig.sh TestArg.sh #执行 $ ./rename.sh Test test 13 files renamed #替换后 $ ls -f | grep "Test" $ ls -f | grep "test" testtrapexit.sh test-bak testemail.txt testArg.sh testtrapsig.sh testdebugtrap.sh testSubStr.txt rmtest.sh test.tar.gz test.tar.bz2 test subshell_test.sh test.tar testfile sedtestReadFile
本节结束
欢迎大家评论交流,发现博文中存在的问题一定要留言哦

浙公网安备 33010602011771号