Perl正则表达式替换在输出中给了我一个额外的字符(单引号)



我编写了以下脚本:

#!/bin/bash
# Add Google Analytics code to every html file in the current folder and subfolders
codice="<script>
  (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
  (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
  m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
  })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
  ga('create', 'UA-XXXXXXXX-X', 'example.net');
  ga('send', 'pageview');
</script>"
original_string=$(printf %q "$codice") # it expands the string in a shell-escaped format
string_to_search='/'
string_to_replace='/'
result_string="${original_string//$string_to_search/$string_to_replace}" # it escapes also slashes "/"
recursive() {
  for file in *; do
    if [ -d "$file" ]; then
      (cd "$file"; recursive)
    fi
    if [[ "$file" =~ .html?$ ]]; then
    perl -i.bak -e 'undef $/; $_=<>; s/</body>n</html>/n'"${result_string}"'n</body>n</html>/gi; print' $file
    echo $file fatto
    fi
  done
}
recursive

这是一个示例输入文件:

<html>
<head>
</head>
<body>
test page
</body>
</html>

脚本执行后,文件被修改为:

<html>
<head>
</head>
<body>
test page

<script>
  (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
  (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
  m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
  })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
  ga('create', 'UA-XXXXXXXX-X', 'example.net');
  ga('send', 'pageview');
</script>'
</body>
</html>

有一件奇怪的事情:为什么在脚本结束标记后面有一个额外的字符(单引号)?感谢您的帮助

我更改的唯一一行使其按预期工作是:

result_string="${codice//$string_to_search/$string_to_replace}" # it escapes also slashes "/"

我不知道它为什么修复了它,也不知道你为什么想要/需要一个printf %q "$codice"来使用

不想对在shell脚本中嵌入"perl-e"的固有肮脏性发表评论。您的正则表达式是:

s/</body>n</html>/n'"${result_string}"'n</body>n</html>/gi;

为了清楚起见,您可能会发现将分隔符"/"换成逗号是值得的。

s,</body>n</html>,n'"${result_string}"'n</body>n</html>,gi;

无论如何,我认为问题的核心是在正则表达式中嵌入一个',但也将其用作perl -e的分隔符。因此,实际上,您将一个字符串文本传递给perl,然后将${result_string}作为shell变量嵌入,然后再继续您的模式。然后用单引号和双引号混合引用。

相反,我强烈考虑将bash脚本重写为纯perl,因为从长远来看,这会让生活变得更好。

#!/usr/bin/perl
# Add Google Analytics code to every html file in the current folder and subfolders
use File::Find; 
use warnings;
use strict;
my $codice="<script>
  (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
  (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
  m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
  })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
  ga('create', 'UA-XXXXXXXX-X', 'example.net');
  ga('send', 'pageview');
</script>";
sub insert_codice
{
  my $filename = $File::Find::name;
  return unless $filename =~ m/.html?Z/;
  { 
    my $backup = "$filename.bak";
    local $/ = undef; 
    open ( my $input_fh, "<", $filename );
    my $input_text = <$input_fh>;
    close ( $input_fh );
    open ( my $backup_fh, ">", "$filename.bak" );
    print {$backup_fh} $input_text;
    close $backup_fh;
    open ( my $output_fh, ">", $filename );
    $input_text =~ s,</body>n</html>,$codicen</body></html>,gi;
    print {$output_fh} $input_text;
    close $output_fh;
  }
}
find ( &insert_codice, "." );

我认为这样的事情会做你想做的事。您可以在File::find模块上找到更多详细信息,这基本上是在perldoc上进行递归目录遍历的一种更整洁的方法:http://perldoc.perl.org/File/Find.html

正如Sobrique已经建议的那样,使用纯perl可以让你的生活更轻松。下面的脚本也使用File::Find,但使用了就地编辑来收紧代码。

#!/usr/bin/perl
# Add Google Analytics code to every html file in the current folder and subfolders
use warnings;
use strict;
use File::Find;
my $codice = do {local $/; <DATA>};
find(sub {
    return unless /.html?Z/;
    local @ARGV = $_;
    local $^I = '.bak';
    my $has_analytics = 0;
    while (<>) {
        $has_analytics ||= m{Qwww.google-analytics.com/analytics.js};
        s{(?=</body>)}{$codice}i unless $has_analytics;
        print;
    }
    #unlink "$_$^I"; # Uncomment if you want to delete the backup
}, "." );
__DATA__
<script>
  (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
  (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
  m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
  })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
  ga('create', 'UA-XXXXXXXX-X', 'example.net');
  ga('send', 'pageview');
</script>

我做了一些增强,如果它认为html文件已经包含它,它将避免添加谷歌分析。此外,如果你想删除备份,你可以取消注释包含unlink的行。

相关内容

最新更新