bash - pdftk删除页码脚本

pdftk删除页码脚本

最近把《Linux命令行与shell脚本编程大全》翻了一遍,想演练一下,于是写出了下面这个脚本,用于调用pdftk删除给定页码生成新文档。编写调试过程中,对bash函数传参、位置参数调用等概念有了更深入的理解,特别是shift,用于处理数量未知的位置参数格外好用。

pdftool.sh
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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
#!/bin/bash
# 对pdftk的简单封装,用于删除指定的页码,以空格分隔,支持形如"5-7"的页码范围。页码输入不必按顺序,类似"12 6-8 1 3"输入是可以正常工作的。

#isPdftkinstalled作用为检查pdftk是否可用,若可用则执行pdftk --version
function isPdftkinstalled {
echo
if [ -z $(whereis pdftk | gawk '{print $2}') ]
then
echo "pdftk未安装或未加入PATH,请检查。"
echo "提示:pdftk已加入Deepin官方源,您可以通过 sudo apt install pdftk 简单安装。"
else
echo $(pdftk --version)
fi
echo
}

#getCouples作用为对输入的页码进行处理,支持输入单页或页码范围,将其转换为数对(获取范围前后页码,以冒号分隔)
function getCouples {
local couples=''
local left_end=''
local right_end=''
while [ -n "$1" ]
do
arg1=$(echo "$1" | gawk -F"[- ]" '{print $1}')
arg2=$(echo "$1" | gawk -F"[- ]" '{print $2}')
left_end=$[ $arg1 - 1 ]
#对应页码范围情况
if [ -n "$arg2" ]
then
right_end=$[ $arg2 + 1 ]
else
#对应单页情况
right_end=$[ $arg1 + 1 ]
fi
couples=$(echo $couples $left_end:$right_end)
shift
done
#数对排序处理,注意sort是针对行的排序,故需要将空格转换成换行
couples=$(echo $couples | tr " " "\n" | sort -t ':' -k 1 -n)
couples=$(refineCouples $couples)
echo $couples
}

#refineCouples作用为合并相邻数对,供getCouples调用
function refineCouples {
local args=''
local isNabour=''
local Num1=$(echo $1 | cut -d ":" -f1)
local Num2=$(echo $1 | cut -d ":" -f2)
local Num3=''
local Num4=''
shift
while [ -n "$1" ]
do
Num3=$(echo $1 | cut -d ":" -f1)
Num4=$(echo $1 | cut -d ":" -f2)
isNabour=$[ $Num2 - $Num3 ]
if [ $isNabour -eq 1 ]
then
Num2=$Num4
else
args=$(echo $args $Num1:$Num2)
Num1=$Num3
Num2=$Num4
fi
shift
done
args=$(echo $args $Num1:$Num2)
echo $args
}

#generateRanges作用为将数对转换为pdftk可用的页码范围
function generateRanges {
local first_Bit=$(echo $1 | cut -d ":" -f1)
local Num1=''
local Num2=''
local args=''
while [ -n "$1" ]
do
Num1=$(echo $1 | cut -d ":" -f2)
if [ -n "$2" ]
then
Num2=$(echo $2 | cut -d ":" -f1)
if [ $Num1 -gt $Num2 ]
then
Num2=$Num1
fi
else
Num2="end"
fi
shift
args=$(echo $args $Num1-$Num2)
done

if [ $first_Bit -gt 0 ]
then
args=$(echo 1-$first_Bit $args)
fi
echo $args
}

#此函数作用为合并相邻页码范围,在使用refineCouples后已无使用必要,可删除
function refineRanges {
local args=''
local isNabour=''
local Num1=$(echo $1 | cut -d "-" -f1)
local Num2=$(echo $1 | cut -d "-" -f2)
local Num3=''
local Num4=''
shift
while [ -n "$1" ]
do
Num3=$(echo $1 | cut -d "-" -f1)
Num4=$(echo $1 | cut -d "-" -f2)
isNabour=$[ $Num3 - $Num2 ]
if [ $isNabour -eq 1 ]
then
Num2=$Num4
else
args=$(echo $args $Num1-$Num2)
Num1=$Num3
Num2=$Num4
fi
shift
echo $Num1
done
args=$(echo $args $Num1-$Num2)
echo $args
}

pdfFile=$1
shift
if [ $# -lt 2 ]
then
echo "Usage:pdftool [filename] [discard pages]"
exit
fi

pagesConserved=$(generateRanges $(getCouples $*))
pdftk_command=$(echo pdftk $pdfFile cat $pagesConserved output new_$(basename ${pdfFile}))
#echo $pdftk_command
$pdftk_command

根据大佬指点,使用bash自身的字符串展开替代cut命令:

pdftool.sh
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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
#!/bin/bash
# 对pdftk的简单封装,用于删除指定的页码,以空格分隔,支持形如"5-7"的页码范围。页码输入不必按顺序,类似"12 6-8 1 3"输入是可以正常工作的。

#isPdftkinstalled作用为检查pdftk是否可用,若可用则执行pdftk --version
function isPdftkinstalled {
echo
if [ -z $(whereis pdftk | gawk '{print $2}') ]
then
echo "pdftk未安装或未加入PATH,请检查。"
echo "提示:pdftk已加入Deepin官方源,您可以通过 sudo apt install pdftk 简单安装。"
else
echo $(pdftk --version)
fi
echo
}

#getCouples作用为对输入的页码进行处理,支持输入单页或页码范围,将其转换为数对(获取范围前后页码,以冒号分隔)
function getCouples {
local couples=''
local left_end=''
local right_end=''
while [ -n "$1" ]
do
arg1=$(echo "$1" | gawk -F"[- ]" '{print $1}')
arg2=$(echo "$1" | gawk -F"[- ]" '{print $2}')
left_end=$[ $arg1 - 1 ]
#对应页码范围情况
if [ -n "$arg2" ]
then
right_end=$[ $arg2 + 1 ]
else
#对应单页情况
right_end=$[ $arg1 + 1 ]
fi
couples=$(echo $couples $left_end:$right_end)
shift
done
#数对排序处理,注意sort是针对行的排序,故需要将空格转换成换行
couples=$(echo $couples | tr " " "\n" | sort -t ':' -k 1 -n)
couples=$(refineCouples $couples)
echo $couples
}

#refineCouples作用为合并相邻数对,供getCouples调用
function refineCouples {
local args=''
local isNabour=''
#local Num1=$(echo $1 | cut -d ":" -f1)
#local Num2=$(echo $1 | cut -d ":" -f2)
local Num1=${1%%:*}
local Num2=${1##*:}
local Num3=''
local Num4=''
shift
while [ -n "$1" ]
do
Num3=${1%%:*}
Num4=${1##*:}
isNabour=$[ $Num2 - $Num3 ]
if [ $isNabour -eq 1 ]
then
Num2=$Num4
else
args=$(echo $args $Num1:$Num2)
Num1=$Num3
Num2=$Num4
fi
shift
done
args=$(echo $args $Num1:$Num2)
echo $args
}

#generateRanges作用为将数对转换为pdftk可用的页码范围
function generateRanges {
local first_Bit=${1%%:*}
local Num1=''
local Num2=''
local args=''
while [ -n "$1" ]
do
Num1=${1##*:}
if [ -n "$2" ]
then
Num2=${2%%:*}
if [ $Num1 -gt $Num2 ]
then
Num2=$Num1
fi
else
Num2="end"
fi
shift
args=$(echo $args $Num1-$Num2)
done

if [ $first_Bit -gt 0 ]
then
args=$(echo 1-$first_Bit $args)
fi
echo $args
}

pdfFile=$1
shift
if [ $# -lt 2 ]
then
echo "Usage:pdftool [filename] [discard pages]"
exit
fi

pagesConserved=$(generateRanges $(getCouples $*))
pdftk_command=$(echo pdftk $pdfFile cat $pagesConserved output new_$(basename ${pdfFile}))
#echo $pdftk_command
pdftk_command

可见使用bash本身的字符串替换更加高效灵活,通过#或%的数量可以制定首次匹配或最长匹配,用来截取文件名或后缀很有用。