Thread perl one liner : string suchen und ersetzen wert (unix) (17 answers)
Opened by bora99 at 2012-05-08 15:07

topeg
 2012-05-09 21:52
#158267 #158267
User since
2006-07-10
2611 Artikel
BenutzerIn

user image
mal sinnvoll überarbeitet:
more (17.0kb):
Code (perl): (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
#!/usr/bin/perl
use warnings;
use strict;

Usage('NO ARGUMENTS!') unless(@ARGV);
Usage() if(grep{$_ eq '-h' || $_ eq '--help'}@ARGV);

my $file=shift(@ARGV) or USAGE('No File defined');

my %changes;
while(@ARGV)
{
  my ($k,$v)=split(/\s*=\s*/,shift(@ARGV),2);
  $changes{$k}=$v;
}

Usage("No Changes defined") unless(%changes);


die("File $file not exists!\n") unless(-e $file);
my $real_filename=$file;
while(-l $real_filename)
{
  $real_filename=readlink($real_filename);
  die("Can't read symbolic Link ($!)\n") unless($real_filename);
  die("File $real_filename not exists!\n") unless(-e $real_filename);
}
die("$real_filename is not a file!\n") unless(-f $real_filename);

my $tmpfile = "$file.tmp";

open(my $rfh, '<', $real_filename) or die("Can't open $real_filename ($!)\n");
open(my $tfh, '>', $tmpfile) or die("Can't open $tmpfile ($!)\n");

while (my $line = <$rfh>)
{
  if($line=~/^[^#]*?([^=\s]+)\s*=/)
  {
    my $key=lc($1);
    $line =~ s/(\Q$key\E\s*=\s*)[^#\s]+(?:\s+[^#\s]+)+/$1$changes{$key}/i if(defined($changes{$key}));
  }
  print $tfh $line;
}

close($tfh) or die("ERROR close $tmpfile ($!)\n");
close($rfh) or die("ERROR close $real_filename ($!)\n");

# neben symbolischen Links gibt es noch über das Dateisystem gelinkete Dateien.
# Siehe unterschied zwischen "ln" und "ln -s"
# Wenn man eine dieser Dateien Ersetzt geht die Verlinkung verloren.
# darum ist es sinnvoll den altern Inhalt zu überschreiben,
# um die Verlinkung zu erhalten.
open($tfh, '<:raw', $tmpfile) or die("Can't open $tmpfile ($!)\n");
open($rfh, '>:raw', $real_filename) or die("Can't open $real_filename ($!)\n");
my $chunk;
print $rfh $chunk while(read($tfh,$chunk,4096));
close($rfh) or die("ERROR close $real_filename ($!)\n");
close($tfh) or die("ERROR close $tmpfile ($!)\n");
unlink($tmpfile) or die("Can't delete $tmpfile\n");

# wenn dir das egal ist kannst du natürlich auch die schnelle Variante nutzen.
#unlink($real_filename) or die("Can't delete $real_filename\n"); # oder als Backup speichern
#rename($tmpfile, $real_filename) or die("Error Can't rename $tmpfile to $real_filename ($!)\n");

exit 0;

########################################################################

sub Usage
{
  my $msg=shift;
  my $out=\*STDOUT;
  if($msg)
  {
    $out=\*STDERR;
    print $out "$msg\n";
  }

  print $out "Usage: $0 file <eintrag>=<wert> [<eintrag>=<wert> [...] ] \n";

  exit 1 if($msg);
  exit 0;
}


  • "i" modifier bei regexp
  • Hilfe bei -h oder --help
  • kürzere Auflösung bei symbolischen Links
  • beliebig viele Ersetzungen
  • bessere Position bei der Erkennung ob eine Datei existiert
  • andere/bessere Dateiersetzung die auch mit gelinkten Dateien klar kommt.


Ich würde nebenbei gerne wissen was bei meiner Form der Ersetzung nicht funktioniert.

Edit: Fehler behoben, suchen/ersetzen Teil verbessert
Last edited: 2012-05-09 23:08:02 +0200 (CEST)

View full thread perl one liner : string suchen und ersetzen wert (unix)