Как использовать Bash для создания массивов со значениями из одной строки из множества файлов? - PullRequest
0 голосов
/ 23 ноября 2018

У меня есть несколько файлов (в одной папке) с одинаковым количеством строк:

a.txt

20
3
10
15
15

b.txt

19
4
5
8
8

c.txt

2
4
9
21
5

Используя Bash, я хотел бы создать массив массивов, которые содержат значение каждой строки в каждом файле.Итак, строка 1 из a.txt, b.txt и c.txt.То же самое для строк со 2 по 5, так что в итоге это выглядит так:

[
   [20, 19, 2],
   [3, 4, 4],
   ...
   [15, 8, 5]
]

Примечание: я испортил форматирование и формулировку.Я изменил это сейчас.

Я на самом деле использую jq, чтобы получить эти списки в первую очередь, поскольку они изначально являются определенными значениями в файле JSON, который я загружаю каждые X минут.Я использовал jq, чтобы получить нужные значения в разные файлы, так как думал, что это продвинет меня дальше, но теперь я не уверен, что это был путь.Если это поможет, вот исходный файл JSON, который я загружаю и начинаю с .

Я рассмотрел различные вопросы, которые в какой-то мере связаны с этим:

Среди прочих.Но ни один из них не касается извлечения значения одной и той же строки из разных файлов.Я не знаю Bash достаточно хорошо, чтобы сделать это, и любая помощь очень ценится.

Ответы [ 3 ]

0 голосов
/ 23 ноября 2018

Вот один из подходов:

$ jq -c -n '[$a,$b,$c] | transpose'  --slurpfile a a.txt  --slurpfile b b.txt  --slurpfile c c.txt 

Обобщение на произвольное количество файлов

В дальнейшем мы будем предполагать, что обрабатываемые файлы могут быть определены с помощью * .txtв текущем каталоге:

jq -n -c '
  [reduce inputs as $i ({}; .[input_filename] += [$i]) | .[]]
  | transpose' *.txt
0 голосов
/ 23 ноября 2018

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

$ paste a.txt b.txt c.txt | jq -Rc 'split("\t") | map(tonumber)'
[20,19,2]
[3,4,4]
[10,5,9]
[15,8,21]
[15,8,5]

Если вы хотите собрать весь результат в одинмассив, передать его в другой экземпляр jq в режиме slurp.(Возможно, есть способ сделать это с помощью одного вызова jq, но это кажется более простым.)

$ paste a.txt b.txt c.txt | jq -R 'split("\t") | map(tonumber)' | jq -sc
[[20,19,2],[3,4,4],[10,5,9],[15,8,21],[15,8,5]]
0 голосов
/ 23 ноября 2018

Я не мог придумать простой способ, но вот один, который я должен сделать:

1.Объедините файлы и создайте CSV-подобный файл

Если на вашем компьютере установлена ​​join, вы можете создавать объединенные записи из двух файлов (например, команда join в SQL).Для этого убедитесь, что ваш файл отсортирован.Я думаю, что самый простой способ - нумерация каждой строки.Это работает как основной идентификатор в SQL.

$ cat a.txt | nl > a.txt.nl
$ cat b.txt | nl > b.txt.nl
$ cat c.txt | nl > c.txt.nl

Теперь вы можете join отсортировать файлы в один.Обратите внимание, что join может объединять только два файла одновременно.Вот почему я перенаправил вывод на следующий join.

$ join a.txt.nl b.txt.nl | join - c.txt.nl > conc.txt

, теперь conc.txt:

1 20 19 2
2 3 4 4
3 10 5 9
4 15 8 21
5 15 8 5

2.Создать json из CSV-подобного файла

Это кажется немного сложным.

jq -Rsn '
    [inputs
     | . / "\n"
     | (.[] | select((. | length) > 0) | . / " ") as $input
     | [$input[1], $input[2], $input[3] ] ]
' <conc.txt

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

  • разделить входной файл по \n
  • разделить заданную строку пробелом, затем выбрать действительные данные
  • поместить разделенные записи в соответствующее место по их индексу

Я использовал этот вопрос для справки: https://stackoverflow.com/a/44781106/10675437

...