Использование инструментов Unix для извлечения строковых значений

Я написал небольшой Perl-скрипт для извлечения всех значений из строки в формате JSON для заданного имени ключа (показано ниже). Итак, если я установлю переключатель командной строки для Perl-скрипта на id, он вернет 1,2 и stringVal из приведенного ниже примера JSON. Этот сценарий выполняет свою работу, но я хочу посмотреть, как другие решат ту же проблему, используя другие инструменты в стиле Unix, такие как awk, sed или perl. Спасибо

{
   "id":"1",
   "key2":"blah"
},
{
   "id":"2",
   "key9":"more blah"
},
{
   "id":"stringVal",
   "anotherKey":"even more blah"
}

Фрагмент Perl-скрипта, извлекающего значения JSON:

my @values;
while(<STDIN>) {
    chomp;
    s/\s+//g; # Remove spaces
    s/"//g; # Remove quotes
    push @values, /$opt_s:([\w]+),?/g; # $opt_s is a command line switch for the key to find
}

print join("\n",@values);

person Steve    schedule 16.11.2009    source источник


Ответы (7)


пялиться

gawk 'BEGIN{
 FS=":"
 printf "Enter key name: "
 getline key < "-"
}
$0~key{
  k=$2; getline ; v = $2
  gsub("\"","",k)
  gsub("\"","",v)
  print k,v
}' file

выход

$ ./shell.sh
Enter key name: id
1, blah
2, more blah
stringVal, even more blah

Если вам просто нужно значение идентификатора,

$ key="id"
$ awk -vkey=$key -F":" '$0~key{gsub("\042|,","",$2);print $2}' file
1
2
stringVal
person ghostdog74    schedule 16.11.2009
comment
Хороший 2-й пример. Что именно делает gsub(\042|,,,$2)? - person Steve; 16.11.2009
comment
он говорит сделать глобальную замену двойной кавычки и запятой. Пожалуйста, проверьте вашу таблицу ascii на предмет значения \042. - person ghostdog74; 17.11.2009

use JSON;

person jheddings    schedule 16.11.2009

Я настоятельно рекомендую использовать модуль JSON. Он будет анализировать ваш ввод json в одной функции (и обратно). Он также предлагает интерфейс ООП.

person Robert Mah    schedule 16.11.2009

Вот очень грубый сценарий Awk для выполнения этой задачи:

awk -v k=id -F: '/{|}/{next}{gsub(/^ +|,$/,"");gsub(/"/,"");if($1==k)print $2}' data
  • -F: указывает ':' в качестве разделителя полей
  • -v k=id устанавливает ключ, который вы ищете.
  • строки, содержащие '{' или '}', пропускаются.
  • первый gsub избавляется от начальных пробелов и завершающих запятых.
  • Второй gsub избавляется от двойных кавычек.
  • Наконец, если k соответствует $1, печатается $2.

data — это файл, содержащий ваш JSON

person Wernsey    schedule 16.11.2009
comment
Отличное решение. Я надеялся на чистый ответ awk, так как я пытаюсь улучшить его с помощью awk. Спасибо. - person Steve; 16.11.2009
comment
@steve, обратите внимание, что результат и ваш результат Perl отличаются. - person ghostdog74; 16.11.2009
comment
Только будьте осторожны: это не удастся, как только в файле появятся пустые строки или формат изменится в малейшей степени. - person Wernsey; 16.11.2009
comment
Я указываю на надежное решение на чистом awk по адресу stackoverflow.com/a/10468771/272427. - person dubiousjim; 06.05.2012

sed (при условии, что файл отформатирован, как указано выше, не более одной записи в строке):

KEY=id;cat file|sed -n "s/^[[:space:]]*\"$KEY\":\"//p"|sed 's/".*$//'
person catwalk    schedule 16.11.2009
comment
конечно, нет необходимости, просто удобнее иметь имя исходного файла ближе к началу скрипта, а не быть похороненным в середине однострочного - person catwalk; 16.11.2009

Почему вы сами разбираете строку, когда есть библиотеки, которые сделают это за вас? json.org содержит библиотеки разбора и кодирования JSON практически для любого языка, о котором вы только можете подумать (и, возможно, некоторых из тех, которые вы не знаете). т). В Перле:

use strict;
use warnings;
use JSON qw(from_json to_json);

# enable slurp mode
local $/;

my $string = <DATA>;
my $data = from_json($string);

use Data::Dumper;
print "the data was parsed as: " . Dumper($data);

__DATA__
[
    {
       "id":"1",
       "key2":"blah"
    },
    {
       "id":"2",
       "key9":"more blah"
    },
    {
       "id":"stringVal",
       "anotherKey":"even more blah"
    }
]

.. производит вывод (я добавил массив верхнего уровня вокруг данных, чтобы он анализировался как один объект):

the data was parsed as: $VAR1 = [
          {
            'key2' => 'blah',
            'id' => '1'
          },
          {
            'key9' => 'more blah',
            'id' => '2'
          },
          {
            'anotherKey' => 'even more blah',
            'id' => 'stringVal'
          }
        ];
person Ether    schedule 16.11.2009

Если вы не против увидеть символы кавычек и двоеточий, я бы просто использовал grep:

grep id file.json

person Tim Henigan    schedule 16.11.2009