Supondo que haja n
linhas de saída não-JSON, o seguinte script curto passará essas linhas como estão e usará jq
para formatar as linhas restantes. A entrada é assumida como entrada padrão para o script e o script usa o número n
do primeiro argumento de linha de comando (ou o padrão é 5 se esse argumento não existir).
#!/bin/sh
n=${1-5}
if [ "$n" -gt 0 ]; then
head -n "$n"
fi
jq .
O script assume que o comando head
consumirá exatamente n
de linhas de entrada. Existem implementações de head
que não se comportam assim e que lerão mais de n
linhas, não deixando nenhuma entrada para jq
processar. O% GNUhead
é bem comportado neste aspecto e funciona como pretendido.
Teste:
$ sh script.sh 2 <file.json
non-json text
on two lines
{
"name": "myapp",
"hostname": "myhost.local",
"pid": 64662,
"source_file_path": "/path/to/src/connector.js",
"req_id": "2339717c-6c3b-4e51-a4b2-5c647efd9c25",
"connector": "abc123",
"level": "INFO",
"req": {
"method": "GET",
"url": "http://backend/server/url"
},
"time": "2016-09-01T06:31:55.099Z",
"v": 0,
"message": "Outgoing request"
}
A seguir, uma variação do que foi mencionado acima, que adiciona uma detecção simplista do início do conteúdo JSON na entrada. Supõe-se que o documento JSON comece na primeira linha que tenha um {
como o primeiro caractere.
Primeiro, o script salva a entrada em um arquivo temporário (que é excluído quando o script é encerrado) e, em seguida, analisa esse arquivo duas vezes. Uma vez para extrair os dados não-JSON e novamente para extrair o documento JSON.
#!/bin/sh
tmpfile=$(mktemp)
trap 'rm -f "$tmpfile"' EXIT
cat >"$tmpfile"
sed -n '/^[^{]/{p;d;}; q' <"$tmpfile"
sed -n '/^{/,$p' <"$tmpfile" | jq .
Teste:
$ sh script.sh <file.json
non-json text
on two lines
{
"name": "myapp",
"hostname": "myhost.local",
"pid": 64662,
"source_file_path": "/path/to/src/connector.js",
"req_id": "2339717c-6c3b-4e51-a4b2-5c647efd9c25",
"connector": "abc123",
"level": "INFO",
"req": {
"method": "GET",
"url": "http://backend/server/url"
},
"time": "2016-09-01T06:31:55.099Z",
"v": 0,
"message": "Outgoing request"
}
Se o uso de um arquivo temporário parece deselegante, a seguinte variação leva o nome do caminho do arquivo de entrada a partir da linha de comando:
#!/bin/sh
infile=$1
sed -n '/^[^{]/{p;d;}; q' <"$infile"
sed -n '/^{/,$p' <"$infile" | jq .