Bash - 将第一行输入变量并显示其余部分而不使用临时文件

时间:2018-02-08 09:46:40

标签: json bash jq aws-cli tee

我收到一些我处理的json,直到它变成文本行。在第一行中,我希望保留一个变量值,并且第一行之后的所有其余值应显示较少或其他工具。

我可以不使用临时文件吗?

上下文是这样的:

aws logs get-log-events --log-group-name "$logGroup" --log-stream-name "$logStreamName" --limit "$logSize" |
 jq '{message:.nextForwardToken}, .events[] | .message' |
 sed 's/^"//g' | sed 's/"$//g'

在第一行中,我想放入变量中的nextForwardToken,其余的都是日志消息。

json看起来像这样:

{
"events": [
    {
        "timestamp": 1518081460955,
        "ingestionTime": 1518081462998,
        "message": "08.02.2018 09:17:40.955 [SimpleAsyncTaskExecutor-138] INFO  o.s.b.c.l.support.SimpleJobLauncher - Job: [SimpleJob: [name=price-update]] launched with the following parameters: [{time=1518081460875, sku=N-W7ZLH9U737B|N-XIBH22XQE87|N-3EXIRFNYNW0|N-U19C031D640|N-6TQ1847FQE6|N-NF0XCNG0029|N-UJ3H0OZROCQ|N-W2JKJD4S6YP|N-VEMA4QVV3X1|N-F40J6P2VM01|N-VIT7YEAVYL2|N-PKLKX1PAUXC|N-VPAK74C75DP|N-C5BLYC5HQRI|N-GEIGFIBG6X2|N-R0V88ZYS10W|N-GQAF3DK7Y5Z|N-9EZ4FDDSQLC|N-U15C031D668|N-B8ELYSSFAVH}]"
    },
    {
        "timestamp": 1518081461095,
        "ingestionTime": 1518081462998,
        "message": "08.02.2018 09:17:41.095 [SimpleAsyncTaskExecutor-138] INFO  o.s.batch.core.job.SimpleStepHandler - Executing step: [index salesprices]"
    },
    {
        "timestamp": 1518082421586,
        "ingestionTime": 1518082423001,
        "message": "08.02.2018 09:33:41.586 [upriceUpdateTaskExecutor-3] DEBUG e.u.d.a.j.d.b.StoredMasterDataReader - Reading page 1621"
    }
],
"nextBackwardToken": "b/33854347851370569899844322814554152895248902123886870536",
"nextForwardToken": "f/33854369274157730709515363051725446974398055862891970561"
}

我需要输入一个变量:

f/33854369274157730709515363051725446974398055862891970561

并显示(或放入其他变量)消息:

08.02.2018 09:17:40.955 [SimpleAsyncTaskExecutor-138] INFO  o.s.b.c.l.support.SimpleJobLauncher - Job: [SimpleJob: [name=price-update]] launched with the following parameters: [{time=1518081460875, sku=N-W7ZLH9U737B|N-XIBH22XQE87|N-3EXIRFNYNW0|N-U19C031D640|N-6TQ1847FQE6|N-NF0XCNG0029|N-UJ3H0OZROCQ|N-W2JKJD4S6YP|N-VEMA4QVV3X1|N-F40J6P2VM01|N-VIT7YEAVYL2|N-PKLKX1PAUXC|N-VPAK74C75DP|N-C5BLYC5HQRI|N-GEIGFIBG6X2|N-R0V88ZYS10W|N-GQAF3DK7Y5Z|N-9EZ4FDDSQLC|N-U15C031D668|N-B8ELYSSFAVH}]
08.02.2018 09:17:41.095 [SimpleAsyncTaskExecutor-138] INFO  o.s.batch.core.job.SimpleStepHandler - Executing step: [index salesprices]
08.02.2018 09:33:41.586 [upriceUpdateTaskExecutor-3] DEBUG e.u.d.a.j.d.b.StoredMasterDataReader - Reading page 1621

提前感谢您的帮助。

4 个答案:

答案 0 :(得分:2)

您可能会认为这有点诡计,但您可以使用tee将所有输出传递给stderr并使用head获取您想要变量的一行:

var="$(command | tee /dev/stderr | head -n 1)"

或者您可以通过一些脚本来解决这个问题:

first=true
while read -r line; do
    if $first; then
        first=false
        var="$line"
    fi
    echo "$line"
done < <(command)

答案 1 :(得分:1)

如果您对将内容存储到变量感兴趣,请在较早的mapfile版本上使用readbash

只需使用read即可获得第一行。我已将-r标记添加到jq打印输出,不带引号

read -r token < <(aws logs get-log-events --log-group-name "$logGroup" --log-stream-name "$logStreamName" --limit "$logSize" | jq -r '{message:.nextForwardToken}, .events[] | .message')
printf '%s\n' "$token"

或使用mapfile

mapfile -t output < <(aws logs get-log-events --log-group-name "$logGroup" --log-stream-name "$logStreamName" --limit "$logSize" | jq -r '{message:.nextForwardToken}, .events[] | .message')

并遍历数组。第一个元素将始终包含您想要的标记ID。

printf '%s\n' "${output[0]}"

其余元素可以迭代,

for ((i=1; i<${#output[@]}; i++)); do
    printf '%s\n' "${output[i]}"
done

答案 2 :(得分:1)

直接地:

O(mp + nm) = O(m(n+p))

- 设置aws logs get-log-events --log-group-name "$logGroup" \ --log-stream-name "$logStreamName" --limit "$logSize" > /tmp/log_data 变量:

nextForwardToken

- 打印所有nextForwardToken=$(jq -r '.nextForwardToken' /tmp/log_data) echo $nextForwardToken f/33854369274157730709515363051725446974398055862891970561 项:

message

jq -r '.events[].message' /tmp/log_data

答案 3 :(得分:1)

我相信以下内容符合规定的要求,假设有类似bash的环境:

x=$(aws ... |
    tee >(jq -r '.events[] | .message' >&2) |
    jq .nextForwardToken) 2>&1

这使得感兴趣的项目可用作shell变量$ x。

请注意,使用jq的sed命令行选项可以避免使用-r进行字符串操作。

只调用一次jq

x=$(aws ... |
 jq -r '.nextForwardToken, (.events[] | .message)' |
 tee >(tail -n +2 >&2) |
 head -n 1) 2>&1

echo "x=$x"