Рейтинг:-1

Как извлечь строку из файла json и поместить в переменную (Linux)

флаг us

У меня есть следующее в одном из моих файлов json file1.json: -

{
  "$quer": {
    "аргументы": [{
      "аргументы": [
        "выбрать\n db1.table1 как вкладку1,\n db1.table2 как вкладку2,\n db1.table3 как вкладку3\n из db1.table4 как вкладку4"
      ],
      "fn": "из-sql",
      "нс": "оп"
    }],
    "фн": "операторы",
    "нс": "оп"
  }
}

Я хочу извлечь строку db1.table4 из этого json-файла и сохраните его в переменной.

Я мало что знаю о sed и awk. Может ли кто-нибудь помочь здесь?

terdon avatar
флаг cn
Откуда нам знать, что извлекать? Должно ли это всегда быть второе слово от первого элемента в массиве `args`? Должно ли это быть что-то после `select\n`? Как мы можем определить часть файла, которую вы хотите извлечь?
Рейтинг:2
флаг ru

Взглянем в jq процессор командной строки JSON, установите, например, с помощью:

sudo apt установить jq

Строка, которую вы хотите, не является значением JSON, это часть значения JSON. Поэтому я предлагаю вам использовать jq чтобы получить строку, которую нужно преобразовать в переменную, например:

my_var=$(jq -r .[$quer].args[0].args[0] file1.json)

Это дает вам переменную, содержащую оператор SELECT:

выберите db1.table1 как tab1, db1.table2 как tab2, db1.table3 как tab3 из db1.table4 как tab4

Затем вам нужно будет использовать другие инструменты, такие как sed, awk, cut и т. д., чтобы получить нужную подстроку из этой переменной. Для вашего конкретного случая это будет работать, но, конечно, может не работать для другого оператора SELECT. Обрезка по разделителю пробелов и возврат 12-го значения:

my_table=$(echo $my_var | cut -d' ' -f12)
Aviator avatar
флаг us
он уже есть, но мой вопрос не связан с json, чтобы использовать команду unix.
terdon avatar
флаг cn
@Aviator `jq` _это_ команда, как и любая другая. Это как раз тот инструмент, который нужно использовать при разборе файлов json.
codlord avatar
флаг ru
Примеры добавлены выше.
terdon avatar
флаг cn
Спасибо! Так понятнее :)
Рейтинг:2
флаг us
  1. Предположим, что строка, которую вы хотите извлечь, находится в одной и той же позиции во всех файлах, которые вы можете использовать. главный, хвост и резать команды с использованием каналов.

  2. Например:

    $ голова -6 файл.json | хвост -1 | вырезать -b 121-129
    db1.таблица
    
  3. А вот пример скрипта, задающего вывод в переменную:

    #!/бин/баш
    v1=$(head -6 file.json | tail -1 | cut -b 121-130)
    эхо "$v1"
    

Вывод скрипта будет db1.table4 что является значением V1 переменный.

Подробнее об этих командах можно прочитать здесь:

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

Aviator avatar
флаг us
большое спасибо. мне помогло.
Рейтинг:1
флаг cn

Как правило, вам следует избегать использования общих инструментов анализа текста для структурированных данных. Поскольку у вас есть файл json, безопаснее и проще использовать специальный анализатор json. В вашем случае вы хотели бы извлечь значение первого элемента массива аргументы который сам является первым элементом массива верхнего уровня аргументы, потомок хэша верхнего уровня $quer:

$ jq '."$quer"."args"[0]["args"]' файл.json
[
  "выбрать\n db1.table1 как вкладку1,\n db1.table2 как вкладку2,\n db1.table3 как вкладку3\n из db1.table4 как вкладку4"
]

Отсюда у вас больше нет структурированных данных, и вам нужно прибегать к более грубым методам. Я не знаю, как вы хотите идентифицировать свою целевую строку, вы этого не объяснили. Итак, в зависимости от того, что вы на самом деле хотите, вы можете сделать:

  1. Пропустить строки, начинающиеся с [ или же ] а затем напечатайте второе слово из оставшихся строк:

    $ jq '."$quer"."args"[0]["args"]' file.json | awk '/^[^][]/{print $2}'
    db1.table1
    
  2. Вывести второе слово второй строки

    $ jq '."$quer"."args"[0]["args"]' file.json | awk 'NR==2{напечатать $2}'
    db1.table1
    
  3. Напечатайте самый длинный участок без пробелов после строки "выбрать\n:

    $ jq '."$quer"."args"[0]["args"]' file.json | grep -oP '"выбрать\n\s*\K\S*'
    db1.table1
    

Если вы объясните, как именно мы должны знать, какую строку извлечь, я мог бы дать вам более целенаправленный ответ.


Для завершения, в вашем конкретный пример, и я подчеркиваю, что это не будет переносимым и почти наверняка потерпит неудачу, если ваши входные данные каким-либо образом изменятся, вы можете напрямую использовать простые текстовые инструменты:

$ grep -oP '"выбрать\n\s*\K\S*' файл.json 
db1.table1

$ awk '$1=="\"выберите\n"{print $2}' файл.json 
db1.table1

$ sed -nE 's/.*"выберите\n\s*(\S+).*/\1/p' файл.json 
db1.table1
флаг hr
Возможно, вы могли бы выполнить некоторые awk-подобные нарезки и нарезки в jq, например `jq -r '."$quer".args[0].args[] | разделить("\n")[-1] | split(" ")[-3]' file.json` или, может быть, что-то регулярное выражение, например `jq -r '."$quer".args[0].args[] | захватить("из(?[^ ]+)") | .a'`
terdon avatar
флаг cn
@steeldriver да, но я подумал, что, поскольку я не знаю, что на самом деле хочет извлечь ОП, я могу также дать несколько простых вариантов.
флаг hr
правда... не понятно

Ответить или комментировать

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