使用printf打印时保留空格

时间:2017-09-14 20:47:27

标签: json bash jq

这是我输入的样子:

pollresp={
    "ImportImageTasks": [
        {
            "Description": "SP",
            "ImportTaskId": "import-ami-123456",
            "Status": "deleted",
            "StatusMessage": "User initiated task cancelation"
        }
    ]
}

使用jq,我基于ImportTaskId过滤对象并打印Status和StatusMessage。

这是我的过滤器表达式的样子:

printf "%s\n%s\n%s" $(echo ${pollresp} |  jq '.ImportImageTasks[] | select(.ImportTaskId=="import-ami-123456") | .ImportTaskId,.Status,.StatusMessage')

输出如下:

"import-ami-123456"
"deleted"
"Userinitiated
task
cancelation"

StatusMessage有空格。我试图保留空格并获得输出:

"import-ami-123456"
"deleted"
"User initiated task cancelation"

我该怎么做?

4 个答案:

答案 0 :(得分:3)

默认情况下,Bash会在空格上拆分参数,因此回显的输出将在空格上进行拆分。

jq '.ImportImageTasks[] | select(.ImportTaskId=="import-ami-123456") | .ImportTaskId,.Status,.StatusMessage' <<< "$pollresp"

将输出:

"import-ami-123456"
"deleted"
"User initiated task cancelation"

答案 1 :(得分:2)

为了清晰和可读性而写,这可能看起来像:

#!/usr/bin/env bash

jq_script='
.ImportImageTasks[]
| select(.ImportTaskId=="import-ami-123456")
| [.ImportTaskId, .Status, .StatusMessage]
| @tsv
'

while IFS=$'\t' read -r importTaskId status statusMessage; do
  printf '%s\n' "$importTaskId" "$status" "$statusMessage"
done < <(jq -r "$jq_script" <<<"$pollresp")

请注意@tsv管道末尾的jq - 生成制表符分隔的输出,while IFS=$'\t' read -r var1 var2 var3循环 - 如BashFAQ #1中所述 - 迭代过来。

(如果在安全敏感的上下文中执行此操作,我建议修改您的jq表达式以从内容字段中删除标签和换行符 - 或者,如果这些是合法数据,{ {3}}并剥离那些)。

答案 2 :(得分:1)

问题不在于jq,而在于您使用bash子shell的方式。这是一个演示差异的脚本。

#!/bin/bash
pollresp='{
    "ImportImageTasks": [
        {
            "Description": "SP",
            "ImportTaskId": "import-ami-123456",
            "Status": "deleted",
            "StatusMessage": "User initiated task cancelation"
        }
    ]
}'

filter='
    .ImportImageTasks[] 
  | select(.ImportTaskId=="import-ami-123456") 
  | .ImportTaskId,.Status,.StatusMessage
'


echo _________________________ with printf "%s\n%s\n%s" unquoted subshell
printf "%s\n%s\n%s" $(echo ${pollresp} | jq "$filter")

echo
echo _________________________ with printf "%s\n" quoted subshell
printf "%s\n" "$(echo ${pollresp} | jq "$filter")"

echo _________________________ with no subshell
jq "$filter" <<< "$pollresp"

echo _________________________ with while/read
while read -r ImportTaskId
      read -r Status
      read -r StatusMessage
do
    printf "%s\n%s\n%s\n" "$ImportTaskId" "$Status" "$StatusMessage"
done < <(jq "$filter" <<< "$pollresp")
echo _________________________ 

以下是显示差异的输出。如果你想在bash中进一步格式化或处理来自jq的结果,我会建议使用while / read方法。

_________________________ with printf %s\n%s\n%s unquoted subshell
"import-ami-123456"
"deleted"
"Userinitiated
task
cancelation"
_________________________ with printf %s\n quoted subshell
"import-ami-123456"
"deleted"
"User initiated task cancelation"
_________________________ with no subshell
"import-ami-123456"
"deleted"
"User initiated task cancelation"
_________________________ with while/read
"import-ami-123456"
"deleted"
"User initiated task cancelation"
_________________________

答案 3 :(得分:0)

请更正以下方法:

echo "$pollresp" | jq '.ImportImageTasks[] | select(.ImportTaskId=="import-ami-123456") | .ImportTaskId,.Status,.StatusMessage'

输出:

"import-ami-123456"
"deleted"
"User initiated task cancelation"