复杂的字符串替换

时间:2016-03-23 14:36:19

标签: regex sed

这个问题的目的是将pdf文件中的/ PageLabels代码(source)替换为另一个。我们必须这样做,因为程序中有一个错误打印pdf(我们无法更改程序)。手工花费了很多时间(我们每小时制作了50个pdf文件)。

然而,为了务实,这个例子可以总结如下。

旧/ PageLabels代码:位于名为a.pdf的原始文件中。

我们使用grep函数来获取不正确的 / PageLabels代码

grep -aPo '/PageLabels\K[^"]*>>]>>' a.pdf

<</Nums[0<</S/r/St 1>>6<</S/r/St 7>>10<</S/r/St 11>>12<</S/r/St 13>>14<</P(1-)/S/D/St 1>>20<</P(2-)/S/D/St 1>>28<</P(3-)/S/D/St 1>>80<</P(4-)/S/D/St 1>>116<</P(A-)/S/D/St 1>>132<</P(B-)/S/D/St 1>>134<</P(C-)/S/D/St 1>>138<</P(D-)/S/D/St 1>>148<</P(E-)/S/D/St 1>>168<</P(F-)/S/D/St 1>>176<</P(G-)/S/D/St 1>>182<</P(Glossary-)/S/D/St 1>>194<</P(Comments-)/S/D/St 1>>]>>

新建/ PageLabels代码我们希望使用以下内容替换“旧/ PageLabels代码”。这是另一个脚本的结果,该脚本重新评估pdf并获得pdf的正确 / PageLabel代码(手动测试和验证)。

<</Nums[0<</S/r/St 1>>12<</P(1-)/S/D/St 1>>17<</P(2-)/S/D/St 1>>32<</P(3-)/S/D/St 1>>98<</P(4-)/S/D/St 1>>130<</P(A-)/S/D/St 1>>153<</P(B-)/S/D/St 1>>154<</P(C-)/S/D/St 1>>158<</P(D-)/S/D/St 1>>187<</P(E-)/S/D/St 1>>230<</P(F-)/S/D/St 1>>242<</P(G-)/S/D/St 1>>247<</P(Glossary-)/S/D/St 1>>259<</P(Comments-)/S/D/St 1>>]>>

它将保存在另一个名为b.pdf

的文件中

我们不知道如何使用 sed 函数编写它。

非常感谢任何想法。

2 个答案:

答案 0 :(得分:0)

我不明白您要从链中替换的具体信息。然而,当我打破链条时,我看到了如下图所示的变化(Stack在试图替换所有特殊字符时变得疯狂,因此将其作为图片放入) Old_new_Chain

如果我假设正确,您希望使用1>>6更改页面标记1>>12,依此类推

如果那就是你想要的,你可以使用以下来代替旧的

cat a.pdf |sed -e 's/1>>20/1>>98/' -e 's/1>>28/1>>130/'等等。 你可以继续添加-e到上面只要shell接受它[它将取决于你的* nix版本]。

或者,您需要编写一个shell脚本来读取每一行并根据某些逻辑替换粒子字段。假设new_chain中的数字与old_chain的差异可以通过某种K因子来表示。

如果您可以按照以下方式发布旧/新数据,并告诉我新旧之间是否存在任何标准差异,我可以提供更多帮助。

希望这会有所帮助。

答案 1 :(得分:0)

您应该使用replace代替sedregex

#! /bin/bash
old=$(grep -aPo '/PageLabels\K[^"]*>>]>>' a.pdf) ## Get Old /PageLabels code
new=$(/tmp/get_correct_code.sh )  ## Get New /PageLabels code
cat a.pdf |replace "$old" "$new" > new_a.pdf

从手册页:

DESCRIPTION
       The replace utility program changes strings in place in files or on the standard input.

       Invoke replace in one of the following ways:

          shell> replace from to [from to] ... -- file_name [file_name] ...
          shell> replace from to [from to] ... < file_name

更新如果您更喜欢使用sed,可以这样试试:

#! /bin/bash
old=$(grep -aPo '/PageLabels\K[^"]*>>]>>' a.pdf) ## Get Old /PageLabels code
new=$(/tmp/get_correct_code.sh )  ## Get New /PageLabels code

# To replace $old with $new, first you'd have to escape those characters like [, ], -
eold=$(echo $old | sed 's@\([][-]\)@\\\1@g')

# Then do the replace using sed
sed "s@$eold@$new@g" a.pdf > b.pdf