昨天遇到一个shell算法问题,需要删除一个文件中连续两行的内容。举个例子,比如删除相邻两行AAAA和BBBB。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
AAAA
BBBB yes
AAAA
BBBB yes
AAAA
# CCCC
BBBB yes
AAAA
# CCCC
BBBB yes
AAAA
BBBB yes
AAAA
BBBB yes
CC
BBBB #不能删除它
AAAA
hello
BBBB no
AAAA和BBBB直接相邻符合要求;AAAA和BBBB之间有空白行符合要求;AAAA和BBBB之间只有注释行符合要求;AAAA和BBBB之间有注释行和空白行也符合要求;某一行前边有空格或者tab也符合要求;如果BBBB多次出现,不能删除到最后出现的BBBB。
目前的想到的方案就是:1.获取从AAAA开始到文件末尾的所有内容;2.将获取的内容清除掉,空白行注释行,和AAAA行;3.判断清除后剩余内容的第一行是否是BBBB;4.是,删除AAAA至BBBB。
那么用shell如何实现这个功能呢。上代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function common::line_deletor() {
common::log_function "common::line_deletor" "$*"
local file=$1
local line1=$2
local line2=$3
line_ret=$(grep -n "^$line1" "$file" 2>/dev/null | head -n 1 2>/dev/null | awk -F: '{print $1}' 2>/dev/null)
sed -n "$line_ret,$ p" "$file" 2>/dev/null | grep -v "^$line1" 2>/dev/null | sed 's/^[ \t]*//g;s/[ \t]*$//g;/^$/d' 2>/dev/null | head -n 1 2>/d
ev/null | grep "$line2" 1>/dev/null 2>/dev/null
if [ "$?" -eq 0 ]; then
sed -i "/$line1/,/$line2/d" "$file"
else
if grep -i "^$line1" "$file" &>/dev/null; then
sed -i "/^$line1.*/d" "$file"
fi
fi
}
1
1
grep -n "^$line1" "$file" 2>/dev/null | head -n 1 2>/dev/null | awk -F: '{print $1}' 2>/dev/null
将会获取line1第一次出现的行号line_ret。
2
1
sed -n "$line_ret,$ p" "$file"
将会获取从line1开始到文件末尾的所有内容。
3
1
grep -v "^$line1" 2>/dev/null | sed 's/^[ \t]*//g;s/[ \t]*$//g;/^$/d'
用来清除掉空白行,注释行以及line1行。
4
1
head -n 1 2>/dev/null | grep "$line2"
去第一行的内容判断是不是line2。
目前的实现方案就是这样,如果想到其他方案,会继续更新。