Как использовать совпадение в AWK для заданного набора данных - PullRequest
0 голосов
/ 26 декабря 2018

Я работаю над обработкой некоторых результатов, полученных с помощью команды curl в AWK, но, несмотря на чтение о match и regexps, у меня все еще есть некоторые проблемы.У меня все написано, но в очень хакерской манере, где используется много подстрок и действительно простое использование совпадений без записи чего-либо с помощью регулярного выражения.

Мои реальные данные немного сложнее, но вот упрощенныйверсия.Предположим, что в строке хранится следующее: str:

[{"DataA":"200","DataBee":"63500","DataC":[3,22,64,838,2]},{"DataA":"190","DataBee":"63100","DataC":[55,22,64,838,2]},{"DataA":"200","DataBee":"63500","DataC":[3,22,64,838,2]}][{"DataA":"200","DataBee":"63500","DataC":[3,22,64,838,2]},{"DataA":"200","DataBee":"63500","DataC":[3,22,64,838,2]}]

Некоторые замечания по поводу этих данных:

Обратите внимание, что есть 3 "набора" данных, разделенных {}в первых скобках [] и 2 комплекта во вторых скобках.Строка всегда содержит по крайней мере один набор данных в каждом наборе скобок и по крайней мере один набор скобок (т.е. она никогда не будет пустой строкой и всегда будет содержать НЕКОТОРЫЕ действительные данные)

Скобкитакже используется для данных DataC, поэтому их необходимо каким-то образом учитывать

Знаки препинания не будут появляться в строке, кроме разделителей - все фактические данные являются буквенно-цифровыми

Поля DataA,DataBee и DataC всегда будут иметь эти имена

Данные для DataC всегда будут ровно 5 числами, разделенными запятыми

Что я хотел бы сделать, это написать цикл, который будет проходить черезстроку и извлеките значения - a = независимо от того, какой DataA (200 в первом случае), b = независимо от того, какой DataBee (63500 в первом случае), и от c [1] до c [5], содержащих значения из DataC,

Мне кажется, что если бы я мог просто получить идеи о том, как сделать это для вышеуказанных данных, я мог бы использовать их для адаптации к своим потребностям.На данный момент у меня есть цикл с использованием substr длиной 30 строк: (

Ответы [ 2 ]

0 голосов
/ 26 декабря 2018

Я бы рекомендовал использовать jq, например:

jq -c '.[]' <<<"$str"
{"DataA":"200","DataBee":"63500","DataC":[3,22,64,838,2]}
{"DataA":"190","DataBee":"63100","DataC":[55,22,64,838,2]}
{"DataA":"200","DataBee":"63500","DataC":[3,22,64,838,2]}
{"DataA":"200","DataBee":"63500","DataC":[3,22,64,838,2]}
{"DataA":"200","DataBee":"63500","DataC":[3,22,64,838,2]}

Для извлечения DataC:

jq -c '.[] | .DataC' <<<"$str"

Вывод:

[3,22,64,838,2]
[55,22,64,838,2]
[3,22,64,838,2]
[3,22,64,838,2]
[3,22,64,838,2]
0 голосов
/ 26 декабря 2018

Для удовольствия, используя awk:

Я использую "сложные" переменные FS и RS для разделения json.Таким образом, у меня есть одно значение max на столбец и 1 данные на строку (DataA, DataBee, DataC).

Чтобы понять использование FS и RS, посмотрите, как работает эта команда:

awk -F",|\":\"|:\\\[" '
    {$1=$1}1
' OFS="\t" RS="\",\"|},{|\\\]" file

(вы можете заменить file на <(curl <your_url>) или <(echo <your_json_str>))

Возвращает:

[{"DataA        200                           
DataBee 63500                                 
DataC"  3       22      64      838     2     

"DataA  190                                   
DataBee 63100                                 
DataC"  55      22      64      838     2     

"DataA  200                                   
DataBee 63500                                 
DataC"  3       22      64      838     2     
}                                             
[{"DataA        200                           
DataBee 63500                                 
DataC"  3       22      64      838     2     

"DataA  200                                   
DataBee 63500                                 
DataC"  3       22      64      838     2     
}                                     

Теперь это похоже на то, что я могу использовать с awk:

awk -F",|\":\"|:\\\[" '
    /DataA/{a=$2}
    /DataBee/{b=$2}
    /DataC/{for(i=2;i<=NF;i++){c[i-1]=$i}}
    a!=""&&b!=""&&c[1]!=""{
        print "a: ", a; 
        print "b: ", b; 
        printf "c: "; 
        for(i in c){
            printf "%s, ", c[i]
        }; 
        print ""; 
        a=""; b=""; c[1]=""
    }
' RS="\",\"|},{|\\\]" file

Эта команда хранит значение внутри переменных и печатает их, когда установлены a и b и C.

Возвращает:

a:  200
b:  63500
c: 3, 22, 64, 838, 2,
a:  190
b:  63100
c: 55, 22, 64, 838, 2,
a:  200
b:  63500
c: 3, 22, 64, 838, 2,
a:  200
b:  63500
c: 3, 22, 64, 838, 2,
a:  200
b:  63500
c: 3, 22, 64, 838, 2,

Для забавы, используяawk, match и this отличный ответ :

awk ' 
function find_all(str, patt) {
        while (match(str, patt, a) > 0) {
            for (i=1; i in a; i++) print a[i]
            str = substr(str, RSTART+RLENGTH)
        }
    }
{
    print "Catching DataA"
    find_all($0, "DataA\":\"([0-9]*)")
    print "Catching DataBee"
    find_all($0, "DataBee\":\"([0-9]*)")
    print "Catching DataC"
    find_all($0, "DataC\":.([0-9]*),([0-9]*),([0-9]*),([0-9]*),([0-9]*)")
}
' file

Returns

Catching DataA
200
190
200
200
200
Catching DataBee
63500
63100
63500
63500
63500
Catching DataC
3
22
64
838
2
55
22
64
838
2
3
22
64
838
2
3
22
64
838
2
3
22
64
838
2

Теперь вы видели, как это уродливо, посмотрите, как легко этоможет использовать python:

import json

data_str = '[{"DataA":"200","DataBee":"63500","DataC":[3,22,64,838,2]},{"DataA":"190","DataBee":"63100","DataC":[55,22,64,838,2]},{"DataA":"200","DataBee":"63500","DataC":[3,22,64,838,2]}][{"DataA":"200","DataBee":"63500","DataC":[3,22,64,838,2]},{"DataA":"200","DataBee":"63500","DataC":[3,22,64,838,2]}]'

while data_str:
    data, index = json.JSONDecoder().raw_decode(data_str)
    for element in data:
        print("DataA: ", element["DataA"])
        print("DataBee: ", element["DataBee"])
        print("DataC: ", element["DataC"])
    data_str = data_str[index:]

Возвращает:

DataA:  200
DataBee:  63500
DataC:  [3, 22, 64, 838, 2]
DataA:  190
DataBee:  63100
DataC:  [55, 22, 64, 838, 2]
DataA:  200
DataBee:  63500
DataC:  [3, 22, 64, 838, 2]
DataA:  200
DataBee:  63500
DataC:  [3, 22, 64, 838, 2]
DataA:  200
DataBee:  63500
DataC:  [3, 22, 64, 838, 2]

Это решение не только более чистое, но и более надежное, если у вас неожиданные результаты или неожиданное форматирование.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...