.txt
我使用提取了文件中 PDF 的元数据pdftk
,现在我尝试将BookmarkPageNumber
每个书签的值减少一个整数。有.txt
这些行:
BookmarkBegin
BookmarkTitle: Preface
BookmarkLevel: 1
BookmarkPageNumber: 10
BookmarkBegin
BookmarkTitle: Author
... and so on
我正在尝试使用 sed 的替代命令来执行此操作,这是迄今为止我所拥有的:
// $1 is the source .txt file; $2 is the decrement
// __ is a placeholder for the variable with the original value
cat $1 | sed "s/BookmarkPageNumber: [0-9]*/BookmarkPageNumber: `expr __ - $2`/" | cat > metadata.txt
如何__
在同一个 sed 表达式中将原始值放入变量中,然后用它替换占位符?
答案1
为此目的,最好使用它awk
,因为它支持算术运算
cat $1 | awk -v d=$2 '/BookmarkPageNumber:/{$2-=d}1'
答案2
awk '!/BookmarkPageNumber:/ {print}; /BookmarkPageNumber:/ {print $1 " " $2-1}' old.txt > new.txt
答案3
另一种选择是使用 shell 本身(以 5 为例,将其更改为您想要减去的实际整数):
while read key val; do
[[ $key == "BookmarkPageNumber:" ]] && let val=val-5;
echo $key $val;
done < file
或者,您可以使用如下工具perl
:
perl -pe 's/(BookmarkPageNumber:\s*)(\d+)$/$1 . ($2-5)/e; ' file
这是另一种awk
方法:
awk '$1~/BookmarkPageNumber:/{$2=$2-5}1;' file
答案4
注意:我刚刚意识到他想将 BookmarkPageNumber 减少一个任意整数,我最初读过这个整数,而我下面的解决方案只能将其减少 1。但是,考虑到我投入的努力,我感到很难完全删除:
--------仅部分解决方案---------
如果您一意孤行只使用 sed,我为您准备了这 1 个行:
sed -r '/^BookmarkPageNumber: /{s/([0-9]*)$/\1@/;:loop {s/0@/@9/;/0@/b loop;};s/1@/_0/;s/2@/_1/;s/3@/_2/;s/4@/_3/;s/5@/_4/;s/6@/_5/;s/7@/_6/;s/8@/_7/;s/9@/_8/;s/ @9+$/ UNDERFLOW/;s/ _0*/ /;s/_//}' $1 >metadata.txt
注意:这仅适用于自然十进制数,我希望这对您来说没问题。
哦,它甚至还有下溢检测功能。因此,如果您希望页码饱和到 0,只需替换UNDERFLOW
为0
我同意任何人所说的这只是智力上的妄想,因为事实就是如此。
ps:您应该检查输入和输出文件描述符是否指向同一个文件,否则如果用户具有写访问权限,文件将被截断。