我是网站开发人员。我工作的代理商使用Dreamweaver作为其模板/库项目功能。库项目真的很方便用于更新导航栏或每页上相同的一些内容。我们大多数时候都使用静态HTML。因此,要更改菜单项,我们使用Dreamweaver库项目,我们更新该项目一次,我们按更新,并在项目的每个html页面上更改它。
但我想创建一个perl脚本,我可以从命令行运行而不是打开GUI,它会更快。
例如,假设我有一个像这样编码的菜单:
$destinationPath = base_path() . '/Folder/Subfolder1/Subfolder2'; // replace with your required destination directory
我会将li项目代码存储在他们自己的文件中:nav.lbi:
<!--MENUITEMS-->
<li><a href="products.html">Products</a></li>
<li><a href="about_us.html">About Us</a></li>
<li><a href="commercial.html">Commercial</a></li>
<li><a href="contact.html">Contact</a></li>
<!--MENUEND-->
perl脚本需要替换每个文件,它会扫描<li><a href="products.html">Products</a></li>
<li><a href="about_us.html">About Us</a></li>
<li><a href="commercial.html">Commercial</a></li>
<li><a href="contact.html">Contact</a></li>
之间的所有文本
和<!--MENUITEMS-->
的内容为nav.lbi。
我首先要在SED中尝试这个,但是SED是针对逐行的东西量身定制的。我已成功使用SED在另一个文件中的某处插入整个文本文件,但这有点不同。使用Perl我知道我应该能够使用nav.lbi的内容替换<!--MENUEND-->
和<!---MENUITEMS-->
的每次出现之间的所有文本,即使它跨越多行。
如果我需要将<!--MENUEND-->
和<!--MENUITEMS-->
标记添加到实际的nav.lbi文件中,因为它会进行搜索和替换,如果这样可以更容易,那也没关系。这样我就可以在多个html文件中更新导航栏,而无需触摸Dreamweaver。
最后要注意的是<!--MENUEND-->
和结束<!--MENUITEMS-->
有多次出现,因为标题中的导航通常与页脚中的导航相同,所以我需要递归更新文件。 / p>
答案 0 :(得分:1)
只需在正则表达式的末尾添加s
即可使点匹配新行。见man perlre
:
# or use File::Slurp;
sub slurp {
my $fn = shift;
open(IN,$fn);
return join('',<IN>);
}
my $_ = slurp("in.html");
my $new_menu_items = slurp("nav.lbi");
s/<!--MENUITEMS-->(.*)<!--MENUEND-->/$new_menu_items/s;
print;
要将输出保存到新文件而不是仅打印它,您需要指定输出文件并打印到它,因此上面的代码将变为:
sub slurp {
my $fn = shift;
open(IN,$fn);
return join('',<IN>);
}
my $_ = slurp("in.html");
my $new_menu_items = slurp("nav.lbi");
open my $output_file, '>', 'output.html';
s/<!--MENUITEM-->(.*)<!--MENUEND-->/$new_menu_items/s;
print $output_file $_;
有关Perl中啜食的更多信息:
http://www.perl.com/pub/2003/11/21/slurp.html
答案 1 :(得分:0)
以下内容建立在Dov Grobgelds的回答之上,但在评论中添加了额外的功能,并在其回答中提到了。准确地说,它运行多行查找并替换目录中的所有html文件并覆盖原始文件:
#!/usr/bin/perl
use strict;
use warnings;
sub slurp {
my $fn = shift;
open(IN,$fn);
return join('',<IN>);
}
my @files = grep ( -f ,<*.html>);
for my $file (@files) {
print "$file\n";
my $_ = slurp("$file");
my $new_menu_items = slurp("nav.lbi");
open my $output_file, '>', "$file";
s/<!--MENUITEMS-->(.*)<!--MENUEND-->/$new_menu_items/s;
print $output_file $_;
}
说明:
第一个问题是如何将输出打印到文件,而不仅仅是终端。 (参考Dov Grobgelds回答比较原始代码)
1.具体说明输出文件是什么:
open my $output_file, '>', 'output.html';
然后将其输出打印到文件:
print;
- 来自原始答案
变为:
print $output_file $_;
现在让你的脚本在目录中的所有html文件上运行,我们需要将这个脚本变成更动态的东西。我们需要将所有.html文件存储在数组中的变量中,然后遍历数组,将每个.html存储到var,然后在每个文件上运行slurp / regex代码。
首先声明保存html文件的变量,并使用当前目录中的.html文件填充它:
my @files = grep ( -f ,<*.html>);
其余的魔法通过将原始slurp和regex代码包装在for循环中来实现:
#for each file in files array, file is stored via my $file:
for my $file (@files) {
#unecessary put prints out file filename loop is working on:
print "$file\n";
#default var becomes current file contents:
my $_ = slurp("$file");
#this part isn't dynamic, its same each loop, there might be a better
#place to put this:
my $new_menu_items = slurp("nav.lbi");
#makes your output filename the same as the input:
open my $output_file, '>', "$file";
#runs the regex replace on the file contents of orig file
s/<!--MENUITEMS-->(.*)<!--MENUEND-->/$new_menu_items/s;
#saves the contents back out to the original file
#(overwriting it with original data loaded after running regex on it:)
print $output_file $_;
}
现在假设您的结束标记不是唯一的,就像在Dreamweaver模板中一样,您可以添加吗?到(。*)只匹配第一次出现,而不是最后一次:
s/<!--MENUITEMS-->(.*?)<!--LIBRARYITEMEND-->/$new_menu_items/s;