0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

AWS CloudShellで出力される"jq: error string and number cannot be added"に対処するには

Last updated at Posted at 2023-01-29

概要

この記事は、AWS CloudShellでjqのjoinを使用する際に発生するエラーの原因と解決方法を説明しています。

AWS CloudShellでのjqエラー

AWS CloudShellで、jqを使用する際に発生するエラーについて説明します。

数値が含まれる配列をjoinしようとすると、jq: error string and number cannot be addedが出力されます。

期待する結果

$ echo '["example",0]' | jq 'join(".")'
"example.0"

実際の結果

$ echo '["example",0]' | jq 'join(".")'
jq: error (at <stdin>:1): string (".") and number (0) cannot be added

原因

このエラーの原因について説明します。

CloudShellにプリインストールされているjqのバージョンは、1.5です。1

$ jq --version
jq-1.5

1.5のjoinにはバグがあり、number型の場合に文字列化されないため、当該エラーが出力されます。

  "def join($x): reduce .[] as $i (null; (.//\"\") + (if . == null then $i else $x + $i end))//\"\";",

このバグは1.6でFixされています。joinのソースを確認すると、number型をtostringで文字列化していることがわかります。

def join($x): reduce .[] as $i (null;
            (if .==null then "" else .+$x end) +
            ($i | if type=="boolean" or type=="number" then tostring else .//"" end)
        ) // "";

issueが上がっていました。

解決手段1(jq1.5で動作するように修正する)

このエラーを解決する手段について説明します。

まず、jq1.5で動作するように修正する方法です。

joinに渡す前に数値を文字列化すれば、1.5でも期待通りに動作します。もちろん1.6でも問題なく動作します。

$ echo '["example",0]' | jq 'map(.|tostring) | join(".")'
"example.0"

解決手段2(jq1.6をインストールする)

次は、jq1.6をCloudShellにインストールする方法です。

ただし、CloudShellで用意されているyumでは、プリインストールされているjqをアップグレードできない2ので、適当なディレクトリにバイナリをダウンロードするようにします。

ディレクトリの永続性について

  • /usr/binにバイナリファイルを配置すると、CloudShell再起動時にファイルが削除されるため、ご注意ください
  • ホームディレクトリに配置した場合はデータが永続化されますが、120日を超えて当該CloudShell環境の利用がないと、削除されますのでご注意ください

実際の例

具体的な例を示し、解決方法を説明します。

ホームディレクトリにインストール先のディレクトリを作成し、バイナリをダウンロードします。ディレクトリは任意ですが、ここではjq1.6とします。

cd ~
mkdir jq1.6
cd jq1.6
wget -O jq https://github.com/stedolan/jq/releases/download/jq-1.6/jq-linux64
chmod +x ./jq 

先述のとおり、1.6でこのバグはFixされているので、期待通りに動作します。

$ ~/jq1.6/jq --version
jq-1.6
$ echo '["example",0]' | ~/jq1.6/jq 'join(".")'
"example.0"

エイリアスを設定すると、便利です。

$ echo "alias jq=~/jq1.6/jq" >> ~/.bashrc
# エイリアスをログイン中のシェルに反映
$ . ~/.bashrc
$ echo '["example",0]' | jq 'join(".")'
"example.0"

シェルスクリプトとして実行するには

シェルスクリプトとして実行する場合は、ログイン中のシェル環境が引き継がれないため、エイリアスが未定義となり、jq1.5が実行されてしまうことに注意する必要があります。

join.sh
#!/bin/bash
echo '["example",0]' | jq 'join(".")'
$ bash ./join.sh 
jq: error (at <stdin>:1): string (".") and number (0) cannot be added

この場合は、-iオプションで対話的動作を指定すると、~/.bashrcが読み込まれてスクリプトが実行されるため、期待通りの動作になります。

$ bash -i ./join.sh 
"example.0"

結論

CloudShellで、jqを使用する際に発生するエラーについての対処法をまとめます。

2つの解決手段を説明しました。

解決手段1は、CloudShellの環境を変更する必要がなく、また、1.5と1.6どちらでも動作するため可搬性が高いことがメリットです。3

一方で、解決手段2は、1.6で動作させるので、joinエラー以外の挙動にも対応できることに優位性があります。

状況に応じて、使い分けてください。

参考

  1. 記事投稿時点のバージョンです。将来バージョンアップされる可能性があります。

  2. サポートに確認済みです。

  3. 開発用PCなど自由にインストールできる環境であれば、最新バージョンである1.6が入っていることが多いと思います。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?