Разбить строку JSON в простой Perl или Unix? - PullRequest
3 голосов
/ 27 января 2012

хорошо, так что у меня есть это

{"status":0,"id":"7aceb216d02ecdca7ceffadcadea8950-1","hypotheses":[{"utterance":"hello how are you","confidence":0.96311796}]}

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

echo $x | grep -Po '"utterance":.*?[^\\]"' | sed -e s/://g -e s/utterance//g -e 's/"//g'

, но этоработает только тогда, когда у вас есть grep, скомпилированный с perl и плюс скрипт, который я использую, чтобы получить эту строку JSON, написанную на perl, так что есть ли способ, которым я могу сделать то же самое декодирование в простом скрипте perl или более простой команде unix, или лучшевсе же, c или target-c?

скрипт, который я использую для получения json, находится здесь, http://pastebin.com/jBGzJbMk, и если вы хотите использовать файл, скачайте http://trevorrudolph.com/a.flac

Ответы [ 7 ]

6 голосов
/ 27 января 2012

Как насчет:

perl -MJSON -nE 'say decode_json($_)->{hypotheses}[0]{utterance}'

в форме сценария:

use JSON;
while (<>) {
   print decode_json($_)->{hypotheses}[0]{utterance}, "\n"
}
5 голосов
/ 27 января 2012

Ну, я не уверен, смогу ли я правильно определить, что вы ищете, но это способ декодировать эту строку JSON в perl.

Конечно, вам нужно знать данныеструктура для того, чтобы получить необходимые данные.Строка, которая печатает строку «высказывание», закомментирована в коде ниже.

use strict;
use warnings;
use Data::Dumper;
use JSON;

my $json = decode_json 
q#{"status":0,"id":"7aceb216d02ecdca7ceffadcadea8950-1","hypotheses":[{"utterance":"hello how are you","confidence":0.96311796}]}#;
#print $json->{'hypotheses'}[0]{'utterance'};
print Dumper $json;

Вывод:

$VAR1 = {
          'status' => 0,
          'hypotheses' => [
                            {
                              'utterance' => 'hello how are you',
                              'confidence' => '0.96311796'
                            }
                          ],
          'id' => '7aceb216d02ecdca7ceffadcadea8950-1'
        };

Быстрый взлом:

while (<>) {
    say for /"utterance":"?(.*?)(?<!\\)"/;
}

Или как однострочный:

perl -lnwe 'print for /"utterance":"(.+?)(?<!\\)"/g' inputfile.txt

Однострочник проблематичен, если вы используете Windows, поскольку " интерпретируется оболочкой.

Быстрый взлом # 2:

Надеемся, что он пройдет через любую хеш-структуру и найдет ключи.

my $json = decode_json $str;
say find_key($json, 'utterance');

sub find_key {
    my ($ref, $find) = @_;
    if (ref $ref) {
        if (ref $ref eq 'HASH' and defined $ref->{$find}) {
            return $ref->{$find};
        } else {
            for (values $ref) {
                my $found = find_key($_, $find);
                if (defined $found) {
                    return $found;
                }
            }
        }
    }
    return;
}
1 голос
/ 27 января 2012

Если вы не хотите использовать какие-либо модули из CPAN и использовать регулярные выражения, есть несколько вариантов, которые вы можете попробовать:

# JSON is on a single line:
$json = '{"other":"stuff","hypo":[{"utterance":"hi, this is \"bob\"","moo":0}]}';
# RegEx with negative look behind:
# Match everything up to a double quote without a Backslash in front of it
print "$1\n" if ($json =~ m/"utterance":"(.*?)(?<!\\)"/)

Это регулярное выражение работает, если есть только одно высказывание. Неважно, что еще находится в строке вокруг него, так как он ищет только строку в двойных кавычках после ключа произнесения.

Для более надежной версии вы можете добавить пробел, где это необходимо / возможно, и сделать . в новых строках соответствия RegEx: m/"utterance"\s*:\s*"(.*?)(?<!\\)"/s

Если у вас есть несколько записей для хэша / объекта достоверности высказывания, изменение регистра и странное форматирование строки JSON попробуйте это:

# weird JSON:
$json = <<'EOJSON';
{
    "status":0,
    "id":"an ID",
    "hypotheses":[
        {
            "UtTeraNcE":"hello my name is \"Bob\".",
            "confidence":0.0
        },
        {
            'utterance' : 'how are you?',
            "confidence":0.1
        },
        {
            "utterance"
                : "
                thought
                so!
                ",
            "confidence" : 0.9
        }
    ]
}
EOJSON
# RegEx with alternatives:
print "$1\n" while ( $json =~ m/["']utterance["']\s*:\s*["'](([^\\"']|\\.)*)["']/gis);

Основная часть этого RegEx - "(([^\\"]|\\.)*)". Подробное описание в виде расширенного регулярного выражения:

/
["']    # opening quotes
(       # start capturing parentheses for $1
(       # start of grouping alternatives
[^\\"'] # anything that's not a backslash or a quote
|       # or
\\.     # a backslash followed by anything
)       # end of grouping
*       # in any quantity
)       # end capturing parentheses
["']    # closing quotes
/xgs

Если у вас много наборов данных, и скорость является проблемой, вы можете добавить модификатор o в регулярное выражение и использовать классы символов вместо модификатора i. Вы можете запретить захват альтернатив $ 2 с помощью скобок в скобках (?:pattern). Тогда вы получите этот окончательный результат:

m/["'][uU][tT][tT][eE][rR][aA][nN][cC][eE]["']\s*:\s*["']((?:[^\\"']|\\.)*)["']/gos

Да, иногда Perl выглядит как большой взрыв на фабрике скобок; -)

1 голос
/ 27 января 2012

Исходя из наименования, можно выдвинуть несколько гипотез.Печатает высказывание каждой гипотезы:

echo '{"status":0,"id":"7aceb216d02ecdca7ceffadcadea8950-1","hypotheses":[{"utterance":"hello how are you","confidence":0.96311796}]}' | \
   perl -MJSON::XS -n000E'
      say $_->{utterance}
         for @{ JSON::XS->new->decode($_)->{hypotheses} }'

Или как сценарий:

use feature qw( say );
use JSON::XS;
my $json = '{"status":0,"id":"7aceb216d02ecdca7ceffadcadea8950-1","hypotheses":[{"utterance":"hello how are you","confidence":0.96311796}]}';
say $_->{utterance}
   for @{ JSON::XS->new->decode($json)->{hypotheses} };
0 голосов
/ 17 ноября 2012

Тьфу, да, я придумал другой ответ, я изучаю python, и он читает массивы как в своем формате python, так и в том же формате, что и json, так что я сделал только один вкладыш, когда ваша переменная равна x

python -c "print ${x}['hypotheses'][0]['utterance']"
0 голосов
/ 13 ноября 2012

Просто наткнулся на другой хороший способ сделать это, я наконец-то нашел, как получить доступ к командной строке JavaScript-движка Mac OS X, вот сценарий,

alias jsc='/System/Library/Frameworks/JavaScriptCore.framework/Versions/A/Resources/jsc'
x='{"status":0,"id":"7aceb216d02ecdca7ceffadcadea8950-1","hypotheses":[{"utterance":"hello how are you","confidence":0.96311796}]}'
jsc -e "print(${x}['hypotheses'][0]['utterance'])"
0 голосов
/ 27 января 2012

понял это для unix, но хотел бы увидеть ваши perl и c, target-c ответы ...

echo $X | sed -e 's/.*utterance//' -e 's/confidence.*//' -e s/://g -e 's/"//g' -e 's/,//g'

: D

короткая копия того же седа:

echo $X | sed -e 's/.*utterance//;s/confidence.*//;s/://g;s/"//g;s/,//g'
...