Analisar du resultado usando sed

2

Olá eu estou tentando analisar o resultado do du comando, mas eu não sei como fazê-lo sem loop eu executo o comando abaixo

du -shm /var/vmail/mailboxes/domain/*/mail

meu resultado é uma lista, por exemplo:

80 /var/vmail/mailboxes/domain/USER1/mail 
150 /var/vmail/mailboxes/domain/USER2/mail 
220 /var/vmail/mailboxes/domain/USER3/mail 

A lista acima eu quero transformá-lo para json objeto com o abaixo:

{USER1: 80, USER2:150, USER3:220 }

ou pelo menos ter algo:

80 USER1
150 USER2
220 USER3

Eu tentei com sed -e , mas sem sucesso, alguma idéia?

    
por user1521944 03.05.2018 / 16:34

5 respostas

2
du -shm /var/vmail/mailboxes/domain/*/mail | awk -F '[ /]' '{ print $1, $7 }'

Com a entrada de du no formato que você fornece, isso produziria

80 USER1
150 USER2
220 USER3

O programa awk simplesmente seleciona os campos apropriados da saída de du . Ele interpreta cada linha como campos delimitados por espaços ou barras.

awk -F '[ /]' '{ print $1, $(NF - 1) }' também funcionaria.

Para colocar isso em JSON, use jq :

du -shm /var/vmail/mailboxes/domain/*/mail |
awk -F '[ /]' '{ print $1, $7 }' |
jq -sR 'split("\n")[0:-1] | map(split(" ")) | map({(.[1]):.[0]}) | add'

Isso produziria

{
  "USER1": "80",
  "USER2": "150",
  "USER3": "220"
}

A expressão jq primeiro divide a entrada em elementos de matriz separados (um por linha de entrada) e, em seguida, os divide novamente em espaços em submatrizes. Neste ponto, temos

[
  [
    "80",
    "USER1"
  ],
  [
    "150",
    "USER2"
  ],
  [
    "220",
    "USER3"
  ]
]

Depois disso, os objetos são criados com o segundo elemento em cada subarray como a chave e o primeiro como o valor:

[
  {
    "USER1": "80"
  },
  {
    "USER2": "150"
  },
  {
    "USER3": "220"
  }
]

O add no final nos dá o resultado final.

    
por 03.05.2018 / 17:49
3

tente

du -sm /var/vmail/mailboxes/domain/*/mail |
  sed 's:/var/vmail/mailboxes/domain/::; s:/mail::'

onde

  • s:/mail:: substituirá /mail por nada

para ir ao json

du -sm /var/vmail/mailboxes/domain/*/mail |
  sed 's:/var/vmail/mailboxes/domain/::; s:/mail::' |
  awk 'BEGIN { sep="{" ;} { printf "%s \"%s\":%s",sep,$2,$1; sep="," } END { printf "}\n"}'
    
por 03.05.2018 / 16:38
2

Você pode usar awk para converter para o formato de duas colunas:

$ du -shm | awk -F/ '{print $1" "$(NF - 1)}'
80  USER1
150  USER2
220  USER3

Para JSON, tente:

$ du -shm | awk -F/ '{print "\""$(NF - 1)"\":"$1}' | paste -sd, | printf "{$(cat)}" | jq
{
  "USER1": 80,
  "USER2": 150,
  "USER3": 220
}
    
por 03.05.2018 / 17:50
1

jq combina muito bem com texto não processado, ou seja, o sinal -R , por exemplo:

du -sm /var/vmail/mailboxes/domain/*/mail |
jq -R '
  split(" ") |
    .[0]                      as $size |  # Remember size 
    .[1] | split("/") | .[-2] as $name |  # Extract username
    { ($name) : ($size) }                 # Compose object
' 

Dá a você:

{
  "USER1": "80"
}
{
  "USER2": "150"
}
{
  "USER3": "220"
}

Para mesclar os objetos, use uma segunda invocação jq :

... | jq -s add

Saída:

{
  "USER1": "80",
  "USER2": "150",
  "USER3": "220"
}

Ou no modo compacto:

... | jq -sc add

Saída:

{"USER1":"80","USER2":"150","USER3":"220"}
    
por 03.05.2018 / 18:04
1

Isso é um pouco difícil de fazer com sed . No entanto, aqui está uma sugestão comentada que funciona com o GNU sed:

parse.sed

s|([^ ]+) .*/([^/]+)/.*|  "" : ,|   # Extract size and name in json-format
1h; 1!H                                 # Correctly add them to hold-space
$ {
  z                                     # Clear pattern-space
  s/^/\{/                               # Prepend start-curly-brace
  G                                     # Fetch formatted json from hold-space
  s/,$//                                # Remove last comma
  s/$/\n\}/                             # Append end-curly-brace
  p                                     # Print
}

Execute assim:

du -shm /var/vmail/mailboxes/domain/*/mail | sed -Enf parse.sed

Ou como um verso:

du -shm /var/vmail/mailboxes/domain/*/mail |
sed -Ene 's|([^ ]+) .*/([^/]+)/.*|  "" : ,|;1h;1!H;${z;s/^/\{/;G;s/,$//;s/$/\n\}/;p}'

Saída nos dois casos:

{
  "USER1" : 80,
  "USER2" : 150,
  "USER3" : 220
}
    
por 03.05.2018 / 18:24