Como localizar e mover uma linha de texto dentro de um arquivo?

5

Eu preciso alterar uma posição de linha de texto dentro de um arquivo; de uma posição de linha para outra, abaixo de um texto definido.

Por exemplo, eu tenho o seguinte bloco de texto (no arquivo /etc/pam.d/system-auth)

account  required   pam_unix.so
account  sufficient pam_localuser.so
account  required   pam_permit.so
account  required   pam_tally2.so

E eu quero "mover" a última linha para a segunda linha (abaixo da que contém o pam_unix.so)

Como isso pode ser feito usando um comando Perl?

    
por Andres 18.12.2013 / 21:55

4 respostas

2

Usou esta solução alternativa para resolver meu problema ...

/bin/grep "pam_tally2.so" /etc/pam.d/system-auth
if [ "$?" -eq "0" ]; then

#looks for line existence (pam_tally2.so) and delete it (if present)

/usr/bin/perl -i -pe 'chomp,$_.="" if /account\s.*required\s.*pam_tally2.so/' /etc/pam.d/system-auth
/usr/bin/find  /etc/pam.d/system-auth.bkp | /usr/bin/xargs perl -pi -e 's/account\s*required\s*pam_tally2.so//'

#inserts the -deleted- line underneath pam_unix.so line, as desired. Creating a 'moving line' result.

/usr/bin/perl -i -pe 'chomp,$_.="\n" if /account\s.*required\s.*pam_unix.so/' /etc/pam.d/system-auth
/usr/bin/perl -i -pe 'chomp,$_.="\naccount     required      pam_tally2.so\n" if /account\s.*required\s.*pam_unix.so/' /etc/pam.d/system-auth
fi
    
por 20.12.2013 / 16:48
6

Você pode fazer isso usando o módulo Tie::File , que liga as linhas de um arquivo a uma variável de matriz:

perl -MTie::File -e '
        tie @lines,"Tie::File","your_file_here";
        $last_line = pop @lines;
        splice @lines,1,0,$last_line
'

A variável empatada ( @lines ) se torna mágica, no sentido de que quaisquer operações de matriz que você realize afetam as linhas do arquivo ao qual ela está vinculada.

    
por 18.12.2013 / 22:01
3

Você poderia fazer:

perl -e '@l=<>;($l[1],$l[$#l])=($l[$#l],$l[1]);print @l' < file 1<> file

(observe que ele substitui o arquivo no lugar sem rede de segurança).

com ex :

ex -sc 'd|1 put|wq' file
    
por 18.12.2013 / 22:04
1

Para responder à pergunta com mais precisão:

#!/usr/bin/perl
use List::MoreUtils qw(firstidx lastidx);  # you may have to install this from CPAN
use autodie;
use File::Copy;

my $f = '/etc/pam.d/system-auth';
open my $fh, '<', $f;
my @lines = <$fh>;
close $fh;

# find the first and last "auth" lines:
my $first = firstidx {/^account\b/} @lines;
my $last = lastidx {/^account\b/} @lines;

# remove
my $removed = splice @lines, $last, 1;
# insert
splice @lines, $first+1, 0, $removed;

# backup first
copy $f, "$f.bak";
open my $fh, '>', $f;
print $fh join('', @lines);
close $fh;
    
por 20.12.2013 / 20:35