LINUX.ORG.RU

Решено | Конвертировать file.txt в формат file.json через Bash

 , , ,


0

1

Hello there,

есть необходимость (тестовое задание) написать скрипт, который примет как аргумент текстовый файл, а на выходе создаст новый файл на основе старого в JSON формате.

К примеру сам input.txt выглядит так:

[ Asserts Samples ], 1..2 tests

-----------------------------------------------------------------------------------
not ok 1 expecting command finishes successfully (bash way),
7ms

ok 2 expecting command prints some message (the same as above, bats way), 10ms

-----------------------------------------------------------------------------------
1 (of 2) tests passed, 1 tests failed, rated as 50%, spent 17ms

А по итогу должно новый файл должен выглядеть так:

{
 "testName": "Asserts Samples",
 "tests": [
  {
   "name": "expecting command finishes successfully (bash way)",
   "status": false,
   "duration": "7ms"
  },
  {
   "name": "expecting command prints some message (the same as above, bats way)",
   "status": true,
   "duration": "10ms"
  }
 ],
 "summary": {
  "success": 1,
  "failed": 1,
  "rating": 50,
  "duration": "17ms"
 }
}

Т.е. как видно из примера есть:

  1. Первая строка, где нас интересует только название в квадратных скобках
  2. Две разделительные строки, которые никому вообще не сдались
  3. n-ое количество строк, где важен результат (true/false), самое название (от номер до запятой) и потраченное время.
  4. Самая последняя строка, где и будет результат (сколько success, сколько failed, rating и общее duration).

И в общем в теории в input.txt может быть и другая инфа (больше тестов, а значит больше строк и другие данные в summary), однако структура одна и та же: название, разделители, тесты, результат.

Считаю себя достойным newbie и поэтому сам пока додумался только до идеи, но не до реализации. Пробовал через jq, однако проще головой удариться о собственный локоть.

Update. По итогу решил таким образом

#!/bin/bash

#create path to redirect output.json to same directory as output.txt
path=$(dirname $1)

#create variables for name line, test lines and result line
firstline=$(cat $1 | head -n +1 | cut -d "[" -f2 | cut -d "]" -f1)
testname=$(echo $firstline)

tests=$(cat $1 | tail -n +3 | head -n -2)

results=$(cat $1 | tail -n1)

#create main JSON variable
json=$(jq -n --arg tn "$testname" '{testname:$tn,tests:[],summary:{}}')

#test's names, status, duration and updating JSON variable
IFS=$'\n'
for i in $tests
do
    if [[ $i == not* ]]
    then
	    stat=false
    else
	    stat=true
    fi

    if [[ $i =~ expecting(.+?)[0-9] ]]
    then
	    var=${BASH_REMATCH[0]}
	    name=${var%,*}
    fi

    if [[ $i =~ [0-9]*ms ]]
    then
	    test_duration=${BASH_REMATCH[0]}
    fi

    json=$(echo $json | jq \
	    --arg na "$name" \
	    --arg st "$stat" \
	    --arg dur "$test_duration" \
	    '.tests += [{name:$na,status:$st|test("true"),duration:$dur}]')
done

#final success, failed, rating, duration and finishing JSON variable

IFS=$'\n'
for l in $results
do
    if [[ $l =~ [0-9]+ ]]
    then
	    success=${BASH_REMATCH[0]}
    fi

    if [[ $l =~ ,.[0-9]+ ]]
    then
	    v=${BASH_REMATCH[0]}
	    failed=${v:2}
    fi

    if [[ $l =~ [0-9]+.[0-9]+% ]] || [[ $l =~ [0-9]+% ]]
    then
	    va=${BASH_REMATCH[0]}
	    rating=${va%%%}
    fi

    if [[ $l =~ [0-9]*ms ]]
    then
	    duration=${BASH_REMATCH[0]}
    fi

    json=$(echo $json | jq \
                --arg suc "$success" \
                --arg fa "$failed" \
                --arg rat "$rating" \
	        --arg dur "$duration" \
	        '.summary += {success:$suc|tonumber,failed:$fa|tonumber,rating:$rat|tonumber,duration:$dur}')
done

#redirect variable's output to file
echo $json | jq "." > $path"/output.json"


Последнее исправление: BlackMllk (всего исправлений: 7)
Ответ на: комментарий от BlackMllk

Скопировал твою портянку себе в nvim, и не ругается. Работает –значит, хорошо. Причёсывать код, в твоей ситуации, смысла нет.

ashot ★★★★
()
Ответ на: комментарий от DMITRY

Позитивно мыслишь. На лоре только так.))

ashot ★★★★
()
Ответ на: комментарий от ashot

Ну причёсывать не в том смысле «чтобы красиво смотрелось», а чтобы если что-то из того, что я сделал, можно было сделать проще, правильнее или элегантнее, я хотя бы знал как. Но спасибо за содействие :D

BlackMllk
() автор топика
Ответ на: комментарий от BlackMllk

какое-же всё-таки этот ваш баш нечитабельное говно

anonymous
()
Ответ на: комментарий от ashot

Чем тут баш-то провинился?

эмм, он абсолютно не приспособлен для написания чего-то сложнее однострочников, очень плохо зделоли, вощем

и, да, альтернативы есть

anonymous
()

bash, convert, json, txt

Извращенцы, каждый DevOps обязан знать питон как раз чтобы вот так гибрид ёжика с носорогом не выводить.

peregrine ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.