为什么 bash 和 git-bash 结果不同?

为什么 bash 和 git-bash 结果不同?

新手想学习bash和jq。我在 Windows 机器上,所以我想用 git bash 进行测试 - 我认为 git bash 与在 Linux 上运行的 bash 相同。

对于我的测试,我尝试将 JSON 中的列表提取到变量中。然而,我得到了(我认为的)奇怪的结果,所以我在 Docker 容器中的 Ubuntu 上尝试了相同的代码。 Ubuntu 给了我预期的结果。

左边是在 Docker 中运行的 Ubuntu。右侧是 git bash。有人可以解释为什么两个结果不同吗?

bash 示例

抱歉,正文如下:

乌班图:

root@ac88bd1c736e:/usr/local/bin# cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=22.04
DISTRIB_CODENAME=jammy
DISTRIB_DESCRIPTION="Ubuntu 22.04.2 LTS"
root@ac88bd1c736e:/usr/local/bin# jq --version
jq-1.6
root@ac88bd1c736e:/usr/local/bin# ls -la
total 20
drwxr-xr-x 1 root root 4096 Mar  8 16:48 .
drwxr-xr-x 1 root root 4096 Mar  1 02:03 ..
-rwxr-xr-x 1 root root   56 Jul 25  2022 service.py
-rwxr-xr-x 1 root root   96 Mar  7 18:21 test.json
root@ac88bd1c736e:/usr/local/bin# cat test.json
{
        "foo": "bar",
        "access": [
                "rangers",
                "avs"
        ],
        "blah": {
                "bizz": "buzz"
        }
}root@ac88bd1c736e:/usr/local/bin# foo=`cat test.json | jq .access`
root@ac88bd1c736e:/usr/local/bin# echo $foo
[ "rangers", "avs" ]
root@ac88bd1c736e:/usr/local/bin#

git bash:


leehenry@PW03T2JD MINGW64 ~/..../bash
$ git --version
git version 2.39.2.windows.1

leehenry@PW03T2JD MINGW64 ~/..../bash
$ jq --version
jq-1.6

leehenry@PW03T2JD MINGW64 ~/..../bash
$ cat test.json
{
        "foo": "bar",
        "access": [
                "rangers",
                "avs"
        ],
        "blah": {
                "bizz": "buzz"
        }
}
leehenry@PW03T2JD MINGW64 ~/..../bash
$ foo=`cat test.json | jq .access`

leehenry@PW03T2JD MINGW64 ~/..../bash
$ echo $foo
 ]avs"ers",

leehenry@PW03T2JD MINGW64 ~/..../bash
$

答案1

这是 CRLF 与 LF 行终止符的问题。

我希望

$ cat test.json | jq .access

看起来相当正常,每个输出 CR 都是不可见的,然后 LF 将我们带到下一行。

您可以通过以下方式验证

$ cat test.json | jq .access | hexdump -C

或者通过管道更紧凑地通过| hd.请注意 0x0d CR 和 0x0a LF。

之后,apt install dos2unix 您可以通过管道传输 jq 的输出来修复它| dos2unix,并根据需要使用 hexdump 进行验证。


联机bash帮助页相当长。这里是具体的地方

$ foo=`cat test.json | jq .access`

绊倒了你。

命令替换...

Bash 通过以下方式执行扩展:用命令的标准输出替换命令替换,并删除所有尾随换行符。

因此,可以将其视为tr删除了 LF,但保留了 CR。

另请注意此变量:

IFS

内部字段分隔符用于扩展后的字拆分以及使用 read 内置命令将行拆分为字。默认值为<space><tab><newline>

Grep'ing for angle newline 揭示了更多出现这种情况的地方。

因此,如果您要要求bash解析jq包含 CR 的输出,您可能需要调整您的IFS设置。

或者,选择更适合您需求的计算上下文。


十六进制转储 通常是 Ubuntu 的标准配置。

https://packages.ubuntu.com/jammy/amd64/bsdextrautils/filelist

如果丢失,您可以使用apt install bsdmainutils它来将其拉入。

相关内容