Thread search & replace in Textfile (15 answers)
Opened by futhark at 2010-11-23 18:31

topeg
 2010-11-29 20:09
#143198 #143198
User since
2006-07-10
2611 Artikel
BenutzerIn

user image
Ich arbeite häufig mit verschachtelten Arrays und Hashes. (Mit einer gut durchdachten Datenstruktur kann man sich eine Menge Arbeit ersparen.) Solche Strukturen mit Bash-aufrufen zu Filter/Verarbeiten ist eine Qual, da Bash so was nicht kennt und man mit Trennzeichen und ähnlichem darum herum operieren muss.

Mir ist die Kürze nicht so wichtig ob es 100 oder 500 Zeilen ist ist mir egal. Ich habe auch mal so gedacht und alles möglichst kurz gehalten. Aber nach einer weile merkt man dass es durch aus nicht der Übersichtlichkeit dient. Wenn ich "wegwerf"-Scripte (Scripte mit begrenztem Einsatzzeitraum) schreibe, dann schreibe auch so was auch stenographisch, aber wenn es länger leben soll, dann achte ich auf den Stiel, denn andere sollen das irgendwann auch mal lesen können.

ich sehe keinen großen unterschied in:
Code: (dl )
system("sed -i -e 's/remount,ro,noatime/remount,rw,noatime/g' ${PATH}/etc/inittab") == 0 or die("Error replace failed! ($?)");

und
Code (perl): (dl )
eval{local($^I,@ARGV,$/) = ("",${PATH}/etc/inittab); $_=<>; s/remount,ro,noatime/remount,rw,noatime/g; return 1} or die("replace failed ($@)");


Aber wenn man etwas mehr Fehlerbehandlung haben will ist es so, meine ich, besser:

Code (perl): (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
sub replace_in_file
{
  my $file=shift;
  my $regexp=shift;
  my $replace=shift;
  my $txt=eval{local(@ARGV,$/)=($file); <>} or die("ERROR Load $file ($@)\n");
  $txt=~s/$regexp/&$replace/eg;
  open(my $fh, >, $file) or die("ERROR write $file ($!)")
  print $fh $txt;
  close($fh);
}

replace_in_file("${PATH}/etc/inittab",qr/remount,ro,noatime/,sub{return 'remount,rw,noatime'});

Die Funktion kann man dann auch in ein Paket packen und am Anfang laden. Dann schreibt man sie nur einmal und alle korrekturen werden für alle scripte, die sie laden wirksam. Ich habe mittlerweile ein große Sammlung von Modulen.

Da sieht ein script dann ungefähr so aus:
Code (perl): (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
#!/usr/bin/perl
use strict;
use warnings;
use file_ops qw(load_or_die save_or_die);
use text_ops qw(replace_simple);

my $file="/etc/fstab";

my $txt=load_or_die($file);
if(replace_simple(\$txt,'remount,ro,noatime','remount,rw,noatime'))
{ save_or_die($file,$txt); }
else
{ print "Nothing Changed\n" }

wobei hinter "replace_simple" kein echter regulärer Ausdruck steckt sondern eine Kombination aus "index" und "substr" das ist schneller :)

View full thread search & replace in Textfile