Розбір результату за допомогою sed

Здравствуйте, я намагаюся розібрати результат команди du, але я не знаю, як це зробити без циклу Я виконую команду нижче

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

моїм результатом є список, наприклад:

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

Наведений вище список я хочу перетворити на об'єкт json за допомогою наведеного нижче:

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

або принаймні мати щось:

80 USER1
150 USER2
220 USER3

Я намагався з sed -e , але без успіху, якісь ідеї?

2
Покажіть, що ви пробували.
додано Автор Oliv, джерело

5 Відповіді

спробуйте

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

де

  • s:/mail:: will replace /mail by nothing

перейти до 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"}'
3
додано
JSON вимагає, щоб ключі мали подвійний рядок. Зміна оператора printf на printf "% s \ _"% s \ _ ":% s", sep, $ 2, $ 1;
додано Автор Tim Kennedy, джерело
du -shm /var/vmail/mailboxes/domain/*/mail | awk -F '[ /]' '{ print $1, $7 }'

З входом від du у форматі, який ви надаєте, це буде вироблятися

80 USER1
150 USER2
220 USER3

Програма awk просто вибирає відповідні поля з виводу du . Він інтерпретує кожний рядок як поля, розділені пробілами або косою рискою.

awk -F '[ /]' '{ print $1, $(NF - 1) }' would also work.

Щоб отримати це у JSON, використовуйте 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'

Це призвело б

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

Вираз jq спочатку розбиває вхідні дані на окремі елементи масиву (по одному на рядок вводу), а потім знову розбиває їх на пробіли в підполя. На даний момент у нас є

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

Після цього об'єкти створюються з другим елементом в кожному подмассиве як ключ і першим як значенням:

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

add в кінці дає нам кінцевий результат.

2
додано

Ви можете використовувати awk для перетворення у формат 2 стовпців:

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

Для JSON спробуйте:

$ du -shm | awk -F/ '{print "\""$(NF - 1)"\":"$1}' | paste -sd, | printf "{$(cat)}" | jq
{
  "USER1": 80,
  "USER2": 150,
  "USER3": 220
}
2
додано

jq does pretty well with raw-text, i.e. the -R flag, e.g.:

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
' 

Дає вам:

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

Щоб об'єднати об'єкти, скористайтеся другим викликом jq :

... | jq -s add

Вихід:

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

Або в компактному режимі:

... | jq -sc add

Вихід:

{"USER1":"80","USER2":"150","USER3":"220"}
1
додано
Навіщо використовувати другий виклик jq , коли ви можете просто прикласти add до кінця першого конвеєра jq ?
додано Автор Tejaswi Yerukalapudi, джерело
Ах, тому що вони не в масиві.
додано Автор Tejaswi Yerukalapudi, джерело
на цьому рішенні я отримую помилку jq: error (на : 1): розділений вхід і роздільник повинні бути рядками
додано Автор Chetan, джерело
@Kusalananda: він обтікає кожен об'єкт
додано Автор Thor, джерело
@ user1521944: ви використовуєте jq version1.5?
додано Автор Thor, джерело

Це трохи складно зробити з sed . Проте, наведена пропозиція з коментарями, яка працює з GNU sed:

parse.sed

s|([^ ]+) .*/([^/]+)/.*|  "\2" : \1,|   # 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
}

Запустіть його так:

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

Або як один лайнер:

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

Вихідні дані в обох випадках:

{
  "USER1" : 80,
  "USER2" : 150,
  "USER3" : 220
}
1
додано
ІТ КПІ - JavaScript
ІТ КПІ - JavaScript
504 учасників

співтовариство javascript розробників в Telegram