Comment find et déplacer une ligne de text à l'intérieur d'un file?

J'ai besoin de changer une position de ligne de text à l'intérieur d'un file; d'une position de ligne à l'autre, en dessous d'un text défini.

Par exemple, j'ai le bloc de text suivant (sur le file /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 

Et je veux "déplacer" la dernière ligne sur la 2ème ligne (en dessous de celle qui contient pam_unix.so)

Comment cela peut-il être fait en utilisant une command Perl?

Vous pouvez le faire en utilisant le module Tie::File qui lie les lignes d'un file à une variable de tableau:

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

La variable liée ( @lines ) devient magique dans le sens où les opérations de tableau que vous effectuez affectent les lignes du file auquel il est lié.

Vous pourriez faire:

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

(notez qu'il remplace le file en place sans filet de security).

Avec ex :

 ex -sc 'd|1 put|wq' file 

Utilisé cette solution de contournement pour résoudre mon problème …

 /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 

Pour répondre à la question plus précisément:

 #!/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;