仅在特定部分进行搜索和替换

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了仅在特定部分进行搜索和替换相关的知识,希望对你有一定的参考价值。

我有几千个.html文件,我需要搜索并将硬编码的服务器名称替换为相对路径,但仅限于页脚。

EG

<body>
   <a href="http://hardcoded/something">This is ok</a>      
   ... much more content here
   <div class="footer">
       <a href="http://hardcoded/something">Change this one</a>      
   </div>
</body>

有没有工具可以进行这种搜索和替换?

答案

编辑

在发布这个答案后,我把它改进成了better answer。之所以留下这个答案是因为它有大部分的评论,并且是精致代码的垫脚石。


完整代码:

嫦娥.评论

:- set_prolog_flag(double_quotes, codes).

eos([], []).

dcg_change_002(Html) -->
    { Footer_start_tag = "<div class="footer">" },
    anything(Footer_prefix),
    Footer_start_tag, !,
    anything(Anchor_prefix),
    anchor_2(Anchor), !,
    rest_2(Rest), !,
    {
        string_codes(Anchor_prefix,Anchor_prefix_codes),
        string_codes(Anchor,Anchor_codes),
        string_codes(Rest,Rest_codes),
        append(Footer_prefix,Footer_start_tag,Part_1),
        append(Part_1,Anchor_prefix_codes,Part_2),
        append(Part_2,Anchor_codes,Part_3),
        append(Part_3,Rest_codes,Html)
    }.

anything([]) --> [].
anything([C|Cs]) -->
     [C],
     anything(Cs).

rest_2([]) --> call(eos).
rest_2([C|Cs]) -->
    + call(eos),
     [C],
     rest_2(Cs).

anchor_2("<a href="http://changed/something">") --> "<a href="http://hardcoded/something">".

测试用例:

:- begin_tests(html_dcg).

test(002) :-
    HTML_in = "c
<body>
   <a href="http://hardcoded/something">This is ok</a>
   <div class="footer">
       <a href="http://hardcoded/something">Change this one</a>
   </div>
</body>",
    Expected_HTML_out = "c
<body>
   <a href="http://hardcoded/something">This is ok</a>
   <div class="footer">
       <a href="http://changed/something">Change this one</a>
   </div>
</body>",
    string_codes(HTML_in,HTML_in_codes),
    DCG = dcg_change_002(HTML_out_codes),
    phrase(DCG,HTML_in_codes,Rest),
    string_codes(HTML_out,HTML_out_codes),
    format('~nHTML: ~n`~w''~n',[HTML_out]),
    assertion( HTML_out == Expected_HTML_out ),
    assertion( Rest == [] ).

:- end_tests(html_dcg).

示例运行测试:

SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software.
Please run ?- license. for legal details.

For online help and background, visit http://www.swi-prolog.org
For built-in help, use ?- help(Topic). or ?- apropos(Word).

?- consult("C:/change.pl").
true.

?- run_tests.
% PL-Unit: html_dcg 
HTML: 
`<body>
   <a href="http://hardcoded/something">This is ok</a>
   <div class="footer">
       <a href="http://changed/something">Change this one</a>
   </div>
</body>'
. done
% test passed
true.

通常,测试不会输出结果,例如format('~nHTML: ~n``~w''~n',[HTML_out])但它被添加,所以你可以在测试中看到没有样板代码的结果。

由于这个更接近应该做的,这里是一个解释。

Prolog通常使用谓词编写,他们使用运算符:-。 DCG是不同的,使用-->。 DCG被翻译成常规Prolog,DCG可以通过使用{ ... }包括常规Prolog。

DCG处理字符代码,在这种情况下因为这是所有ASCII文本,你可以使用ASCII table,但是尝试读取ASCII字符列表很难,所以,

:- set_prolog_flag(double_quotes, codes).

告诉编译器将" ... "之间的任何内容转换为字符代码列表。

测试从测试用例开始

:- begin_tests(html_dcg).
:- end_tests(html_dcg).

设置一个名为htm_dcg和的测试模块

test(002) :-

有一个名为002的测试谓词。

HTML_in = "c
<body>
   <a href="http://hardcoded/something">This is ok</a>
   <div class="footer">
       <a href="http://hardcoded/something">Change this one</a>
   </div>
</body>"

这使用=/2(统一),它不是赋值,将HTML文本绑定到变量HTML_in,但由于这是一个单独的模块,而不是代码,它是一个字符串,不会转换为字符代码列表。 c是一个escape character,允许<body>在下一行开始而不添加 到输入。 "也必须作为"逃脱为Prolog。

Expected_HTML_out = "c
<body>
   <a href="http://hardcoded/something">This is ok</a>
   <div class="footer">
       <a href="http://changed/something">Change this one</a>
   </div>
</body>"

同样为Expected_HTML_out

由于DCG需要代码,因此将字符串转换为代码

string_codes(HTML_in,HTML_in_codes)

实际上接下来的两行将被写成一行

phrase(dcg_change_002(HTML_out_codes),HTML_in_codes,Rest)

但这有点长而令人困惑。

phrase/3是从谓词到DCG的转换,以及为什么我在这个例子中明确地将接下来的两行写为

DCG = dcg_change_002(HTML_out_codes),
phrase(DCG,HTML_in_codes,Rest)

这样你就可以看到dcg_change_002/2是一个DCG,它将返回HTML结果。它以codes命名,表明它作为字符代码列表返回,而不是字符串。 Rest过度杀戮但过去常常遇到一些罕见的错误

 assertion( Rest == [] )

由于HTML作为字符代码列表返回,因此将其转换回字符串

string_codes(HTML_out,HTML_out_codes)

这样它就可以用了

format('~nHTML: ~n`~w''~n',[HTML_out])

打印HTML以证明有效的工作和

assertion( HTML_out == Expected_HTML_out )

表明代码返回预期的结果。

至于DCG,切入点是

dcg_change_002(Html) -->

并证明文本可以用作可匹配的模式

{ Footer_start_tag = "<div class="footer">" }

所以问题是要抓住所有文本到Footer_start_tag并完成

anything(Footer_prefix)

然后匹配Footer_start_tag

Footer_start_tag, !,

!将停止回溯,并且对于这次讨论来说太先进了,但是提高了性能,但它的使用在纯度圈中是不受欢迎的(长时间讨论,不要问)。

anything(Anchor_prefix)

现在我们在页脚中抓住所有文本到Anchor

    anchor_2(Anchor), !,

这里Anchor

anchor_2("<a href="http://changed/something">") -->  
    "<a href="http://hardcoded/something">".

它与您要替换的代码匹配

"<a href="http://hardcoded/something">".

并返回要将其更改为的代码

 "<a href="http://changed/something">"

你实际上可以制作一个这些规则的表格,如果你想要输入中的同一个位置,可以一次更改多个匹配项,例如这个锚点

最后抓住剩下的文字。

rest_2(Rest), !,

现在对于代码的一部分,我仍然不满意。

因为它全部在{ ... }内,所以它不是DCG,而是在DCG中嵌入的常规Prolog。

{

    string_codes(Anchor_prefix,Anchor_prefix_codes),
    string_codes(Anchor,Anchor_codes),
    string_codes(Rest,Rest_codes),

这是字符串到代码的更多转换。

    append(Footer_prefix,Footer_start_tag,Part_1),
    append(Part_1,Anchor_prefix_codes,Part_2),
    append(Part_2,Anchor_codes,Part_3),
    append(Part_3,Rest_codes,Html)

将所有字符列表重新附加到一个列表中,并将变量HTML与结果绑定。

}.

}只退出嵌入式代码。

anything([]) --> [].
anything([C|Cs]) -->
     [C],
     anything(Cs).

是一个标准的递归调用,只是抓取单个字符C并使用|将它们构建到一个列表中。

rest_2([]) --> call(eos).
rest_2([C|Cs]) -->
    + call(eos),
     [C],
     rest_2(Cs).

另一个标准的递归调用只是抓住单个字符C并使用|将它们构建成一个列表,但是这个正在寻找End Of Stream因此eos+是Prolog的做法。

我知道很多人,如果不是大多数读过这个,这看起来很简单,但实际上它应该那么简单。您没有看到或听到更多程序员这样做的原因是学习逻辑编程,例如Prolog,很难,甚至那时Prolog上的很多课程都没有接近DCG。我花了好几年时间才达到这个水平,即便如此,按照大多数标准来说,这个代码并不是那么好,它可以完成工作,并且编写速度快,功能多样。

我希望发布另一个更高级和更简单的版本,但实际上这是我第一次尝试使用带有HTML的DCG。

另一答案
:- use_module(library(dcg/basics)).

:- set_prolog_flag(double_quotes, codes). 

dcg_change_004(Html) -->
    string(Footer_prefix_codes),
    { Footer_start_tag_codes = "<div class="footer">" },
    Footer_start_tag_codes,
    string(Anchor_prefix_cod

以上是关于仅在特定部分进行搜索和替换的主要内容,如果未能解决你的问题,请参考以下文章

仅在设备屏幕的特定部分显示谷歌地图折线

仅在父片段中的操作栏中显示搜索视图

OpenCV用另一个值替换特定像素值

如何通过Dreamweaver批量对整个站点或目录进行代码搜索或部分全部替换

TabLayout - 如何仅在选项卡上加载片段

仅在特定条件下将 NaN 替换为“-”符号,Python-Pandas