使用 sed 减少数字

使用 sed 减少数字

.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,只需替换UNDERFLOW0

我同意任何人所说的这只是智力上的妄想,因为事实就是如此。

ps:您应该检查输入和输出文件描述符是否指向同一个文件,否则如果用户具有写访问权限,文件将被截断。

相关内容