Как я могу переформатировать поле GECOS с помощью Perl или awk? - PullRequest
0 голосов
/ 03 февраля 2010

Я хочу отсканировать файл passwd и изменить порядок слов в поле комментария с имя-фамилия на имя-фамилия и принудительно ввести фамилию в столицы.

Итак, измените каждую строку с:

jbloggs:x:9999:99:Joe Bloggs:/home/jbloggs:/bin/ksh

до:

jbloggs:x:9999:99:BLOGGS Joe:/home/jbloggs:/bin/ksh

Я новичок в Perl и у меня проблемы с различными разделителями полей в awk. Цени любую помощь.

Ответы [ 6 ]

2 голосов
/ 03 февраля 2010

Используйте Passwd :: Unix или Passwd :: Linux .

1 голос
/ 03 февраля 2010
$ perl -pe 's/^((.*:){4})(\S+)\s+(\S+?):/$1\U$4\E, $3:/' \
    /etc/passwd >/tmp/newpasswd

Чтобы переписать только тех пользователей, которые вошли в систему в течение последних шестидесяти дней согласно lastlog, вы можете использовать

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

как в

$ ./fixusers /etc/passwd >/tmp/fixedusers
1 голос
/ 03 февраля 2010

Это обработает файл, когда вы его прочитаете, и поместит записи нового формата в массив @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);
}
1 голос
/ 03 февраля 2010

$ awk -v FS=":" '{split($5, a, " "); name = toupper(a[2]) " " a[1]; gsub($5, name); print $0}' passwd

Не будет работать, если у вас есть отчество.

Редактировать: более удобочитаемая версия

awk -v FS=":" '
{
    split($5, name_parts, " ")
    name = toupper(name_parts[2]) " " name_parts[1]
    gsub($5, name)
    print $0
}' passwd
1 голос
/ 03 февраля 2010
$ 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
1 голос
/ 03 февраля 2010

Автономный пример:

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

Как сценарий (вывод в STDOUT; должен перенаправить вывод в файл):

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";
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...