2017-03-09 3 views
0

Sie brauchen Hilfe. Ich war auf der Suche nach einem ganzen Tag ohne eine Lösung zu finden, die speziell auf meine Bedürfnisse zugeschnitten ist.Suchen und Linien in der Datei auf String basierend löschen, aber letzte Vorkommen halten

In einer Datei:

Lots 
of 
other 
lines 
... 
... 
# [email protected] ..........1323 <- Do not include '# Client=HOSTNAME' 
# [email protected] ..........123123 <- Do not include '# Client=HOSTNAME' 
[email protected] ....rndChars.... <- delete line 
[email protected] ....rndChars.... <- delete line 
[email protected] ....rndChars.... <- delete line 
[email protected] ....rndChars.... <- delete line 
[email protected] ....rndChars.... <- keep last occurrence 
[email protected] ....rndChars.... <- keep last occurrence 
[email protected] ....rndChars.... <- delete line 
[email protected] ....rndChars.... <- delete line 
[email protected] ....rndChars.... <- keep last occurrence 
... 
... 
more 
lines 

Ich brauche alle Zeilen passend zu finden „Client =“ oder mehr und löschen Sie die Linien mit Ausnahme des letzten Auftretens. Problem ist, ich weiß nie, wie der Hostname sein wird.

Ausgang sollte sein:

Lots 
of 
other 
lines 
... 
... 
# [email protected] ..........1323 <- Do not include '# Client=HOSTNAME' 
# [email protected] ..........123123 <- Do not include '# Client=HOSTNAME' 
[email protected] ....rndChars.... <- keep last occurrence 
[email protected] ....rndChars.... <- keep last occurrence 
[email protected] ....rndChars.... <- keep last occurrence 
... 
... 
more 
lines 

Thx im Voraus.

+0

Was haben Sie bisher versucht? –

Antwort

0

Perl zur Rettung. Lesen Sie die Datei zweimal, behalten Sie die letzte Zeilennummer pro Host in einer Hash-Tabelle.

#!/usr/bin/perl 
use warnings; 
use strict; 

my $client_re = qr/Client=(.*?)@/; 

my $filename = shift; 

open my $IN, '<', $filename or die $!; 

my %lines; 
while(<$IN>) { 
    next if /^#/; 

    # Overwrite the line number if already present. 
    $lines{$1} = $. if /$client_re/; 
} 

seek $IN, 0, 0; # Rewind the file handle. 
$. = 0;   # Restart the line counter. 
while (<$IN>) { 
    if (! /^#/ && (my ($hostname) = /$client_re/)) { 
     print if $lines{$hostname} == $.; # Only print the stored line. 
    } else { 
     print; 
    } 
} 
0

Mit tac & awk:

tac file | awk '/^Client/{ if(!a[$1]){a[$1]++;print};next}1' | tac 

Ausgang:

$ tac file | awk '/^Client/{ if(!a[$1]){a[$1]++;print};next}1' | tac 
Lots 
of 
other 
lines 
... 
... 
# [email protected] ..........1323 <- Do not include '# Client=HOSTNAME' 
# [email protected] ..........123123 <- Do not include '# Client=HOSTNAME' 
[email protected] ....rndChars.... <- keep last occurrence 
[email protected] ....rndChars.... <- keep last occurrence 
[email protected] ....rndChars.... <- keep last occurrence 
... 
... 
more 
lines 
0
sed -r ':a;N;$!ba;:b;s/(.*)(Client=[^@]+\b)[^\n]+\n*(.*\2)/\1\3/;tb' file 
Verwandte Themen