Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何使用Perl或awk重新格式化GECOS字段?_Perl_Awk - Fatal编程技术网

如何使用Perl或awk重新格式化GECOS字段?

如何使用Perl或awk重新格式化GECOS字段?,perl,awk,Perl,Awk,我想扫描passwd文件,将注释字段中的单词顺序从firstname-lastname更改为lastname-firstname,并强制将姓氏改为大写 因此,将每一行更改为: jbloggs:x:9999:99:Joe Bloggs:/home/jbloggs:/bin/ksh 致: 我是Perl新手,在awk中使用不同的字段分隔符时遇到问题。 感谢您的帮助。独立示例: use strict; use warnings; my $s = 'jbloggs:x:9999:99:Joe Blogg

我想扫描
passwd
文件,将注释字段中的单词顺序从firstname-lastname更改为lastname-firstname,并强制将姓氏改为大写

因此,将每一行更改为:

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

我是Perl新手,在awk中使用不同的字段分隔符时遇到问题。 感谢您的帮助。

独立示例:

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
作为脚本(输出到标准输出;必须将输出重定向到文件):

使用严格;
使用警告;
而(){
咀嚼;
我的@tokens=split/:/;
我的($first,$last)=拆分/\s+/,$tokens[4];
$tokens[4]=uc($last)。“$first”;
打印联接(“:”,@tokens),“\n”;
}
$awk-vfs=“:”{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

这将在您读取文件时对其进行处理,并将新的格式条目放入数组@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);
}
openpasswd,“/etc/PASSWD”;
while(){
@字段=拆分/:/;
($first,$last)=拆分(/\s/,$fields[4]);
$last=uc$last;
$fields[4]=“$last$first”;
push@newEntries,join(“:”,@fields);
}
使用或



您在使用AWK字段分隔符时遇到了什么问题?为什么下面的一些解决方案会按原始顺序输出记录?@paul44您使用的是逗号分隔的GECOS信息,还是密码文件中的所有条目都像您的示例一样有“”?
$5=name
工作正常,无需使用
gsub
。另外,我认为您还需要一个
-v of s=:
print
无参数打印
$0
,但我想这是一个品味问题。
$5=name
没有
-v OFS=:
就不能工作。如果不同时包含这两个字段,则会将字段分隔开
gsub()
用结果替换
$0
的内容,因此在我的脚本中,我不需要担心OFS。哦,我知道你现在在那里做什么了。嗯,如果
$5=“”
?危险。对于空的GECOS字段、仅包含一个单词的字段和逗号分隔的字段失败。谢谢大家-这太棒了。如果GECOS包含$firstname$lastname$OTHERSTHOUP-例如-bloggs:x:9999:99:Joe bloggs temp(Sales):/home/jbloggs:/bin/ksh,那么我只想对全名进行操作,如上所述,并丢弃其余的GECOS怎么办,跳过手册
uc
。无论如何,它是等价的…在空的或一个单词的GECOS字段中添加一个空格。对于逗号分隔的字段失败。+1很好的一点…我过于关注特定的示例,没有使其成为一般性的。对于逗号分隔的GECOS字段失败。如果GECOS字段仅由一个单词组成,则在其开头添加一个空格。在这里我们不要走得太远。对于逗号分隔的GECOS字段,这将失败,并给出“在串联(.)或字符串中使用未初始化值$first”某些记录出现错误。逗号分隔的GECOS字段失败。@Dennis对于paul44在问题中没有提到的许多格式,它可能会失败。我已经尽可能地清理了GECOS字段-这对我来说很好-谢谢。顺便问一下,有没有一种简单的方法来获取第一个字段(用户名)并判断他最近是否登录过(比如,与lastlog-u相比),并且只在用户登录时输出,比如说,最近60天,所以将空闲了2个月的用户排除在外?lastlog的格式如下所示。perl是否有一种奇怪的方式来检查最后的登录日期,并排除60天内从未登录或未登录的用户?[root@server1paul]#lastlog-最新bsmith pts/2 172.21.83.181周一10月19日16:10:56+0100 2009的u bsmith用户名端口[root@itdev5[保罗]#lastlog-u jbloggs用户名端口来自最新的jbloggs从未登录上面的所有回复都非常有用-请帮我最后一个忙-干杯。@paul44看到“重写从未登录的用户”的评论了吗?取消对下一行的注释,并在下面几行注释掉“下一个除非…”。
$ 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
awk -v FS=":" '
{
    split($5, name_parts, " ")
    name = toupper(name_parts[2]) " " name_parts[1]
    gsub($5, name)
    print $0
}' passwd
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);
}
$ perl -pe 's/^((.*:){4})(\S+)\s+(\S+?):/$1\U$4\E, $3:/' \ /etc/passwd >/tmp/newpasswd
#! /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