linhas idênticas, exceto pela primeira palavra, coloque a primeira palavra em uma variável

0

Eu tenho arquivos (sudoers) nos quais as linhas podem ser idênticas, exceto pela primeira palavra nelas (usuários diferentes podem executar o mesmo conjunto de comandos). Eu sou capaz de extrair essa linha usando o comando:

# grep -v '^ *%' /etc/sudoers |egrep "$users_in_which_I_am_interested | sort|awk '{sub(/^[ \t]+/, "")};1'

tom ALL = NOPASSWD:/usr/bin/pwdadm,/usr/bin/chsec,/usr/bin/chuser   
jim ALL = NOPASSWD:/usr/bin/pwdadm,/usr/bin/chsec,/usr/bin/chuser   
mark ALL = NOPASSWD:/usr/bin/pwdadm,/usr/bin/chsec,/usr/bin/chuser  
peter ALL = NOPASSWD:/usr/bin/pwdadm,/usr/bin/chsec,/usr/bin/chuser

(/ etc / sudoers é antes disso preparado para remover guias e espaços iniciais e finais e substituir todos os espaços em branco múltiplos entre palavras de espaço único). Essas linhas são idênticas, exceto para o usuário. Eu quero ser capaz de extrair linhas que tenham as mesmas instruções de comando configuradas com as mesmas permissões, mas usuários diferentes, e atribuir o nome de usuário a uma variável e executá-lo através de um loop.

# grep -v '^ *%' /etc/sudoers |egrep "$users_in_which_I_am_interested | sort|awk '{sub(/^[ \t]+/, "")};1'| uniq -cf 1
4 tom ALL = NOPASSWD:/usr/bin/pwdadm,/usr/bin/chsec,/usr/bin/chuser

O problema para mim vem aqui - como encontrar todas as linhas no arquivo que contém

"ALL = NOPASSWD:/usr/bin/pwdadm,/usr/bin/chsec,/usr/bin/chuser"

e atribui o usuário nessas linhas a uma variável? "grep" -ing para a string não é facilmente possível, é uma string desconhecida e pode conter muitos caracteres que precisam ser escapados. ksh, awk e sed podem ser usados (sem perl / python e outras linguagens scr).

    
por Sims 17.07.2011 / 10:48

2 respostas

1

awk '
  {user = $1; $1 = ""; users[$0] = users[$0] sep user; sep = " "}
  END {for (key in users) {print key ">" users[key]}}
'

Dada sua entrada de amostra, isso produz

 ALL = NOPASSWD:/usr/bin/pwdadm,/usr/bin/chsec,/usr/bin/chuser>tom jim mark peter
    
por 17.07.2011 / 13:17
0

Eu sei que você não queria uma solução perl, mas aqui está uma de qualquer maneira. Tem a vantagem que pode manipular se os comandos permitidos estiverem em ordem diferente.

Então, NOPASSWD:/usr/bin/pwdadm,/usr/bin/chsec,/usr/bin/chuser
é tratado como igual a NOPASSWD:/usr/bin/chuser,/usr/bin/pwdadm,/usr/bin/chsec

#!/bin/perl
use strict;
use warnings;

my %hash;

# reads all lines from STDIN
while(<>) {
    chomp;  # removes leading/trailing whitespace

    #splits the input string on whitespace
    my ($user, undef, undef, $cmds) = split;    

    # pulls out list of allowed commands
    my($NP, $cmdlist) = split(/:/, $cmds);

    # Sorts the list of commands and puts it together again
    $cmds = "$NP:".join(',', sort split(/,/, $cmdlist));

    # if the command exists in the hash with a user
    # add the nest user else just adds user                      
    $hash{$cmds} = $hash{$cmds}? "$hash{$cmds} $user" : $user;
}

# print all                                          
foreach my $key (keys %hash) {
    print "$key | ", $hash{$key} ,"\n";
}
    
por 17.07.2011 / 14:19