[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

 

本节结束

 

posted @ 2020-06-15 10:08  workingdiary  阅读(357)  评论(0)    收藏  举报