前言
这篇文章介绍了一个给PDF加书签的案例,重在把多种工具综合使用以解决问题,凡是代码中能体现的信息,不会再作解释,读者如有一定的Linux基础,阅读起来会比较顺畅。
提取PDF文件中的文本
java -jar pdfbox-app-2.0.11.jar ExtractText onenote.pdf onenote.txt
tac onenote.txt > reverse.txt
PDFBox是一个Java平台的PDF处理类库,它的jar包提供了一些命令行接口。
生成原始书签素材
生成二级书签:awk -f script1.awk onenote.txt > bookmark1.txt
script1.awk
/的第 [0-9]+ 页/ {
if(NF == 3)
pagenumber = $2
if(NF == 5)
pagenumber = $4
}
/[0-9]+年[0-9]+月[0-9]+日 [0-9]+:[0-9]+/ {
datelinemet = 1
datelinenumber = NR
}
datelinemet == 1 && NR == datelinenumber + 1 {
datelinemet = 0
print "BookmarkPageNumber: " pagenumber
print "BookmarkLevel: " 2
print "BookmarkTitle: " $0
print "BookmarkBegin"
}
生成一级书签:awk -f script2.awk reverse.txt > bookmark2.txt
script2.awk
BEGIN {
prevpartitionname = "NULL"
partitionname = "NULL"
}
/的第 [0-9]+ 页/ {
if(NF == 3) {
pagenumber = $2
gsub("分区", "", $1)
gsub("的第", "", $1)
partitionname = $1
}
if(NF == 5) {
pagenumber = $4
partitionname = $2
}
}
partitionname != prevpartitionname {
prevpartitionname = partitionname
print "BookmarkBegin"
print "BookmarkTitle: " partitionname
print "BookmarkLevel: " 1
print "BookmarkPageNumber: " pagenumber
}
得到一级书签应该放在bookmark1.txt
中的位置:
n=`wc -l bookmark2.txt | awk '{print $1}'`
grep -n -E -e "`sed -n \"1,$(($n-1))s/\$/\$|/g;s/^/^/g;/BookmarkPageNumber/H;\\$s/$/$/g;\\$g;\\$p\" bookmark2.txt | tr -d "\n"`" bookmark1.txt > bookmark3.txt
bookmark2.txt
相比于bookmark3.txt
缺少一些书签,需要人工比对后按照格式增加到里面。
生成最终书签文件
为后续sed
命令的执行准备脚本:sh script.sh > bookmark4.sed
script.sh
IFS=$'\n'
lns=(`cat bookmark3.txt | cut -d: -f1`)
i=0
for l in `cat bookmark2.txt`; do
if (($i%4 == 0)); then
echo $((${lns[$i/4]}-3))i\\
echo $l\\
else
if (($i%4 == 3)); then
echo $l
else
echo $l\\
fi
fi
i=$(($i+1))
done
执行sed
命令 ,修改bookmark1.txt
为最终版:sed -f bookmark4.sed -i bookmark1.txt
将书签信息导入PDF文件中
pdftk onenote.pdf update_info_utf8 bookmark1.txt output onenote_new.pdf
注意必须使用update_info_utf8
这个选项,而不是类似的update_info
,后者不支持中文书签。
网友评论