How can I do a multi-line find & replace from *Nix

2019-04-13 05:02发布

问题:

I have a bunch of files with some old google tracking code at the bottom of the page:

<script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script>
<script type="text/javascript">
try {
var pageTracker = _gat._getTracker("UA-XXXXXXXXX-1");
pageTracker._trackPageview();
} catch(err) {}</script>

I need to update that so that it has the new version of the GA code:

<script type="text/javascript">
  var _gaq = _gaq || [];
  _gaq.push(['_setAccount', 'UA-xxxxxxx-1']);
  _gaq.push(['_setDomainName', 'site.com']);
  _gaq.push(['_trackPageview']);

  (function() {
    var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
    ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
    var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
  })();

</script>

Normally I would use find . -name "*html" -exec sed s/find/replace/ {} \; to do this, but from what I understand it can't handle multi lines. How do I modify something like this to do a find and replace for multi lines, and how do I easily deal with all that stuff I'd have to escape at the command line? I'm not against creating a bash file.

I am also not against putting the "find" and "replace" stuff in text files and then pulling it into the command that way - at least that should make the escaping part easier.

Thanks!

回答1:

I'd use perl for this.

Something like this should get you started:

#!/usr/bin/perl
use strict;
use warnings;
use File::Slurp qw/slurp/;

my $text = slurp($ARGV[0]);

$text =~ s/foo\nbar/new_and_shiny/;

my $newfile = $ARGV[0] . ".new";

open my $out, ">$newfile" or die "$!"; 
print $out $text;
close $out;

Replace foo\nbar with your old javascript, and don't forget to escape all those special characters ()[] etc.

<edit> Jim Garrison made me edit this answer and add the following:

You can go one step further and replace all the google analytics javascript in your files with a single placeholder string, say 'GOOGLE_ANALYTIC_CODE' that look something like this:

<script>
GOOGLE_ANALYTIC_CODE
</script>

and run the find-and-replace script on these files to replace the 'GOOGLE_ANALYTIC_CODE' with the latest javascript to create the 'deployed' version.

It may take more effort now but it will definitely benefit your future self.

This practice is very nicely documented in the The Pragmatic Programmer book when they dicuss the "DRY principle" (Dont-Repeat-Yourself).

I can't recommend that book enough. Lots and lots of good advice there.

</edit>



回答2:

Assuming you only have one portion of javascript and assuming you can put your new code into a file, here's a Ruby script

#!/usr/bin/env ruby 
newdata = File.open("new").read
olddata = File.open("file").read
puts olddata.gsub(/<script.*<\/script>/m, newdata )

To run it,

$ ruby replace.rb > newfile