I want to scan the passwd
file and change the order of words in the comment field from firstname lastname to lastname firstname, and force the surname to capitals.
So, change every line from:
开发者_JS百科jbloggs:x:9999:99:Joe Bloggs:/home/jbloggs:/bin/ksh
to:
jbloggs:x:9999:99:BLOGGS Joe:/home/jbloggs:/bin/ksh
I'm new to Perl and I'm having problems with different field separators in awk. Appreciate any help.
Use Passwd::Unix or Passwd::Linux.
$ awk -v FS=":" '{split($5, a, " "); name = toupper(a[2]) " " a[1]; gsub($5, name); print $0}' passwd
Won't work if you have middle names though.
Edit: easier to read version
awk -v FS=":" '
{
split($5, name_parts, " ")
name = toupper(name_parts[2]) " " name_parts[1]
gsub($5, name)
print $0
}' passwd
Stand-alone example:
use strict;
use warnings;
my $s = 'jbloggs:x:9999:99:Joe Bloggs:/home/jbloggs:/bin/ksh';
my @tokens = split /:/, $s;
my ($first, $last) = split /\s+/, $tokens[4];
$tokens[4] = uc($last) . " $first";
print join(':', @tokens), "\n";
__END__
jbloggs:x:9999:99:BLOGGS Joe:/home/jbloggs:/bin/ksh
As a script (output to STDOUT; must redirect output to a file):
use strict;
use warnings;
while (<>) {
chomp;
my @tokens = split /:/;
my ($first, $last) = split /\s+/, $tokens[4];
$tokens[4] = uc($last) . " $first";
print join(':', @tokens), "\n";
}
This will process the file as you read it and put the new format entries into the array @newEntries.
open PASSWD, "/etc/passwd";
while(<PASSWD>) {
@fields = split /:/;
($first, $last) = split (/\s/, $fields[4]);
$last = uc $last;
$fields[4] = "$last $first";
push @newEntries, join(':', @fields);
}
$ awk -F":" ' { split($5,a," ");$5=toupper(a[2])" "a[1] } 1 ' OFS=":" /etc/passwd
jbloggs:x:9999:99:BLOGGS Joe:/home/jbloggs:/bin/ksh
$ perl -pe 's/^((.*:){4})(\S+)\s+(\S+?):/$1\U$4\E, $3:/' \ /etc/passwd >/tmp/newpasswd
To rewrite only those users who have logged in within the past sixty days according to lastlog
, you might use
#! /usr/bin/perl -n
use warnings;
use strict;
use Date::Parse;
my($user) = /^([^:]+):/;
die "$0: $ARGV:$.: no user\n" unless defined $user;
if ($user eq "+") {
next;
}
my $lastlog = (split " ", `lastlog -u "$user" | sed 1d`, 4)[-1];
die "$0: $ARGV:$.: lastlog -u $user failed\n"
unless defined $lastlog;
my $time_t = str2time $lastlog;
# rewrites users who've never logged in
#next if defined $time_t && $time_t < ($^T - 60 * 24 * 60 * 60);
# users who have logged in within the last sixty days
next unless defined $time_t && $time_t >= ($^T - 60 * 24 * 60 * 60);
s/^((.*:){4})(\S+)\s+(\S+?):/$1\U$4\E, $3:/;
print;
as in
$ ./fixusers /etc/passwd >/tmp/fixedusers
精彩评论