O awk pode ser usado?

17

Eu gostaria de obter o número ratingcomo saída deste

# nc localhost 9571 
language:
language:en_ZA.UTF-8
language:en_ZW.UTF-8
session-with-name:Ubuntu Classic (No effects):gnome-session --session=2d-gnome
session-with-name:Ubuntu (Safe Mode):gnome-session -f --session=2d-gnome
session-with-name:Ubuntu Classic:gnome-session --session=classic-gnome
xsession:/etc/X11/Xsession
rating:94

Eu posso fazer assim

# nc localhost 9571 | grep rating | cut -d: -f2
94

mas poderia awkser usado para uma solução mais simples?

Sandra
fonte
Esta questão parece estar fora de tópico porque se trata de programação na interface do Awk e é mais relevante no StackOverflow.com
Magellan

Respostas:

32
$ nc localhost 9571 | awk -F: '/rating/ { print $2 }'
quanta
fonte
7
Pode dar resultados incorretos se algum dos valores ou nomes de campo contiver a string "rating", ou seja, um dos nomes da sessão contiver a palavra "rating". Melhor:awk -F: '$1 == "rating" {print $2}'
Ingmar Hupp
3
Ou talvez awk -F: '/^rating:/ { print $2 }'?
um CVn
Eu sei disso, mas faço a conversão com base no comando do OP.
quanta
@IngmarHupp Eu pensei exatamente a mesma coisa. Na verdade, é muito melhor corresponder ao registro exato em questão que editei a resposta com essa alteração. Esperamos que isso ajude as pessoas a aprender a usar o awk de maneira mais eficaz.
11555 Dan Moulding
14

O Quanta me superou, mas incluirei uma sedvariante se você estiver assim:

nc localhost 9571 | sed -ne 's/^rating://p'

O mesmo aconteceu com o MadHatter. Sua solução atual é perfeitamente correta. (Embora eu espere "^rating:"mais do que apenas a palavra para garantir que você obtenha apenas a linha que deseja).

SmallClanger
fonte
Amor que eu sed! É tão subutilizado e subvalorizado ...
Mei
9

Você também pode usar o shell:

nc localhost 9571 | 
while IFS=: read key val; do [[ $key = "rating" ]] && echo "$val"; done
Glenn Jackman
fonte
Esta é a maneira mais rápida - e evita a geração de processos além nc. Agradável!
Mei
7

sim, você pode (e deve) usar (um) awk em vez de (dois) grep e cut:

$ nc localhost 9571 | awk -F: '/^rating:/ { print $2 }'

Certifique-se de combinar sua linha da melhor maneira possível para evitar erros feios.

  • /rating/ trabalho,
  • /^rating/ é melhor (mais seguro),
  • /^rating:/ é melhor (neste caso).
Michał Šrajer
fonte
4

Pode:

nc localhost 9571  | awk -F: '{ if ($1 == "rating") print $2 }' 

(Eu não sei o que você está fazendo com o host local acima, usei sua saída como entrada para o meu comando awk e substituí o "cat" por "nc ..." - mas deve ficar bom.)

Mas por que você faria isso? A maneira UNIX é ter muitas ferramentas pequenas, cada uma das quais faz uma coisa bem, unidas por meio de pipelines, em vez de usar ferramentas multifuncionais maiores. Você precisa selecionar uma única linha correspondente e selecionar um campo a partir dela: grepseleciona linhas com correspondências e cutseleciona campos das linhas de entrada; eles são perfeitos para a tarefa. Mas se você realmente quer fazer tudo em um com awk, bem, lá está.

MadHatter apoia Monica
fonte
Uma razão é que usar grepe cutrequer gerar dois processos e usar awk(ou sed) requer apenas um. Gerar um processo é computacionalmente caro. Além disso, ao contrário de use perlou ruby(et al), sede awksão muito mais leves na frente.
Mei
2
Bastante justo, embora observe que o tamanho do binário awk no meu sistema (F15) é de 360948 bytes, enquanto os binários grep e cut juntos são 170824. Portanto, menos ciclos com apenas um fork + exec, mas mais memória e mais IO para tirar o disco binário. Honestamente, duvido que qualquer uma dessas considerações seja importante nos sistemas modernos, mas se você deseja minimizar, lá está!
MadHatter suporta Monica
Foo Bah: obrigado pela sua proposta de edição, mas o quanta fez uma publicação posterior à minha, que é ainda mais simplificada do que a sua sugestão. Eu preferi o meu porque é mais fácil para um usuário awk de nível básico ver como ele funciona e, portanto, rejeitou sua edição. Obrigado pelo pensamento!
MadHatter suporta Monica
3

Embora a resposta do quanta seja a mais fácil e a que eu escreveria também, aposto que você não sabia que o GNU awk (gawk) também pode fazer networking ? Você pode escrever a coisa toda com o awk se realmente quiser:

BEGIN {
    FS = ":"
    f = "/inet/tcp/0/127.0.0.1/9571"
    while ((f |& getline) > 0)
        if ($1 ~ /^rating$/) {print $2}
}

Isso pode ser útil se um servidor não tiver nc instalado, nc tiver permissões restritas ou se você realmente gostar do awk.

Mark McKinstry
fonte
Oooh. Agradável. Rede e um exemplo de coprocessamento.
Dr. Edward Morbius
0

Você também pode usar sed,

nc localhost 9571 | sed -n "s/^rating:\([\d]*\)/\1/p"

Isso garantirá que a "classificação" inicie a linha e que os dígitos sigam o rating:

Sirch
fonte
0

Se Perl é uma opção:

nc localhost 9571 | perl -F: -lane 'print $F[1] if /rating/'

-aa divisão automática de cada linha na @Fmatriz
-F:usa :como separador de campos, em vez do padrão de espaço em branco
/rating/retornar true se o regex encontrado
$F[1]for o segundo elemento da @Fmatriz.
As matrizes Perl começam com o elemento 0, enquanto o awk começa com $ 1

Chris Koknat
fonte