将密钥和值传递给jq的外部命令

时间:2018-02-28 16:44:23

标签: json shell jq

我正在尝试做什么:

使用jq将参数传递给bash脚本中的ffmpeg。  在我定期生成的外部文件中有一个JSON。

{
   "streams":[
      {
         "track":"/var/www/html/stream1.m3u8",
         "link":"http://playertest.longtailvideo.com/adaptive/bipbop/bipbop.m3u8"
      },
      {
         "track":"/var/www/html/stream2.m3u8",
         "link":"https://mnmedias.api.telequebec.tv/m3u8/29880.m3u8"
      },
      {
         "track":"/var/www/html/stream3.m3u8",
         "link":"http://www.streambox.fr/playlists/test_001/stream.m3u8"
      }
   ]
}

这是我根据https://github.com/stedolan/jq/issues/503

中的回复尝试的命令
jq -r '.streams[] | ffmpeg -v verbose -i  \(.link | @sh) -c copy -flags -global_header -hls_time 10 -hls_list_size 6 -hls_wrap 10 -start_number 1 \(.Track | @sh)"' streams.json | sh

但是我收到此错误消息:

jq: error: syntax error, unexpected IDENT, expecting $end (Unix shell quoting issues?) at <top-level>, line 1:
.streams[] | ffmpeg -v verbose -i  \(.link | @sh) -c copy -flags -global_header -hls_time 10 -hls_list_size 6 -hls_wrap 10 -start_number 1 \(.Track | @sh)"                       
jq: 1 compile error

3 个答案:

答案 0 :(得分:3)

原始代码的最短更改只是添加缺少的引号:

jq -r '.streams[] | "ffmpeg -v verbose -i  \(.link | @sh) -c copy -flags -global_header -hls_time 10 -hls_list_size 6 -hls_wrap 10 -start_number 1 \(.Track | @sh)"' streams.json | sh
#                   ^-- this was missing

请注意,"ffmpeg ..."字符串,并包含在引号中。也就是说,你依靠jq为你的shell生成安全的代码 - 因为它具有为此目的明确构建的功能,这并不像想象的那样糟糕;但是,尽可能避免代码生成仍然是更好的做法。

作为避免代码生成并且对所有可能的文件名都安全的替代方法,使用jq生成NUL分隔的轨道/链接对流,并使用BashFAQ #1循环迭代它们:

#!/usr/bin/env bash

while IFS= read -r -d '' track && IFS= read -r -d '' link; do
  ffmpeg -v verbose -i "$link" -c copy -flags -global_header -hls_time 10 \
         -hls_list_size 6 -hls_wrap 10 -start_number 1 "$track" 
done < <(jq -j '.streams[] | ( .track + "\u0000" + .link + "\u0000" )' streams.json) 

答案 1 :(得分:1)

使用

#!/bin/bash

file="$1"
c=0
while true; do
    track=$(jq -r ".streams[$c].track" "$file" 2>/dev/null)
    link=$(jq -r ".streams[$c].link" "$file" 2>/dev/null)
    [[ ! $stream || ! $link ]] && break
    ffmpeg -v verbose -i "$link" -c copy -flags -global_header -hls_time 10 \
        -hls_list_size 6 -hls_wrap 10 -start_number 1 "$track" 
    ((c++))
done

用法:

./script.bash file.json

答案 2 :(得分:0)

使用生成命令:

(用您自己的路径/文件替换file.json

#!/bin/bash

node<<EOF
var j=$(<file.json);
for (var i = 0; i<j.streams.length; i++) {
   console.log("ffmpeg -v verbose -i '" + j.streams[i].link + "' -c copy -flags -global_header -hls_time 10 -hls_list_size 6 -hls_wrap 10 -start_number 1 '" + j.streams[i].track + "'");
}
EOF

输出:

ffmpeg -v verbose -i 'http://playertest.longtailvideo.com/adaptive/bipbop/bipbop.m3u8' -c copy -flags -global_header -hls_time 10 -hls_list_size 6 -hls_wrap 10 -start_number 1 '/var/www/html/stream1.m3u8'
ffmpeg -v verbose -i 'https://mnmedias.api.telequebec.tv/m3u8/29880.m3u8' -c copy -flags -global_header -hls_time 10 -hls_list_size 6 -hls_wrap 10 -start_number 1 '/var/www/html/stream2.m3u8'
ffmpeg -v verbose -i 'http://www.streambox.fr/playlists/test_001/stream.m3u8' -c copy -flags -global_header -hls_time 10 -hls_list_size 6 -hls_wrap 10 -start_number 1 '/var/www/html/stream3.m3u8'