3 votos

Para anular el contenido de los archivos.

Tengo dos archivos, file1.txt y file2.txt , file1.txt es:

 perimeter a=10
perimeter b=15
perimeter c=20
 

file2.txt es:

 perimeter a=12
perimeter b=14
 

Déjeme saber el sed o Perl para anular los valores en file1.txt

La salida de file1.txt debería ser como:

 perimeter a=12
perimeter b=14
perimeter c=20
 

He usado series de comando como

 sed -i -e '/parameter//d r file1.txt' file2.txt
awk -F, 'NR==FNR{a[$1]=$0;next;}a[$1]{$0=a[$1]}1' file1.txt file2.txt
awk -F, 'NR==FNR{a[$1]=$0;next;}a[$1]{$0=a[$1]}1' file2.txt file1.txt
 

Ninguno de estos está ayudando.

1voto

haukex Puntos 115

Algo como esto, tal vez? Guardar esto como por ejemplo script.pl y se ejecutan a través de perl script.pl file1.txt file2.txt y se produce su salida deseado. He hecho algunas suposiciones acerca del formato de archivo, tales como que no hay líneas en blanco o comentarios que usted necesita para preservar.

#!/usr/bin/env perl
use warnings;
use strict;
use Tie::IxHash;

tie my %hash, 'Tie::IxHash';
while (<>) {
    chomp;
    my ($k,$v) = split /=/, $_, 2;
    $hash{$k} = $v;
}
for my $k (keys %hash) {
    print "$k=$hash{$k}\n";
}

Actualización: Una versión sin la dependencia de la Tie::IxHash:

use warnings;
use strict;

my (%hash, @keys);
while (<>) {
    chomp;
    my ($key,$value) = split /=/, $_, 2;
    push @keys, $key unless exists $hash{$key};
    $hash{$key} = $value;
}
for my $key (@keys) {
    print "$key=$hash{$key}\n";
}

Que también puede ser descompuesto en un oneliner:

perl -F= -anle 'exists$h{$F[0]}||push@k,$F[0];$h{$F[0]}=$F[1];END{print"$_=$h{$_}"for@k}' file1.txt file2.txt

Sin embargo, tenga en cuenta que a diferencia de la secuencia de comandos, este oneliner no funcionará correctamente si hay líneas con más de un =.

0voto

Abbas Puntos 3737

Tendrás que ser un poco cuidadoso acerca de cómo reescribir el archivo. No hacer esto:

some_program < file1 > file1

Debido a que la cáscara se ocupa de las redirecciones, antes de iniciar el programa, el > redirección va a truncar el archivo antes de que el programa tenga la oportunidad de leerlo.

Aquí están algunas de las alternativas:

  1. escribir explícitamente a un archivo temporal, sobrescribir el original

    tmpfile=$(mktemp)
    some_program < file1 > "$tmpfile" && mv "$tmpfile" file1
    

    Uso && , de modo que sólo mv si el programa sale con éxito.

  2. el uso de la sponge comando de la moreutils paquete

    some_program < file1 | sponge file1
    
  3. Si usted está usando GNU awk, puede utilizar el -i inplace de la extensión, pero la necesidad de ajustar el programa un poco:

    gawk -i inplace -F= '
        NR == FNR {a[$1] = $0; print; next} 
        $1 in a {$0 = a[$1]} 
        1
    ' file{2,1}.txt
    

Las opciones 2 y 3 utiliza un archivo temporal, pero va a tomar el cuidado de los detalles para usted.

EnMiMaquinaFunciona.com

EnMiMaquinaFunciona es una comunidad de administradores de sistemas en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros sysadmin, hacer tus propias preguntas o resolver las de los demás.

Powered by: