Bash 脚本——将“curl”输出存储在变量中,然后根据变量中的字符串进行格式化

Bash 脚本——将“curl”输出存储在变量中,然后根据变量中的字符串进行格式化

我希望将curl数据放入 shell 脚本变量中,然后使用catawk对该变量进行操作,就像它是一个文件一样。

这可能吗?或者有解决方法吗?我必须将curl命令保存到文件中吗?

curl对于我想要执行的每一位字符串格式化,我是否必须运行几次?

我正在curl访问 ipinfo.io,想输出“city”和“region”的匹配行。我知道如何使用awksed根据需要格式化输出。

例如,尝试curl ipinfo.io/"8.8.8.8"获取 Google DNS IP 地址的结果。

我只想打印“Mountain View”和“California”,最好在同一行,并采用一些常见的格式,例如“Mountain View, California”。

答案1

一般来说,有更合适的方法来解析 JSON 对象,但由于在这种情况下 JSON 对象非常简单,您可以将curl的输出存储在变量中(这是可能的)并只需使用 AWK:

var="$(curl ipinfo.io/"8.8.8.8" 2>/dev/null)"
<<<"$var" awk -F'"' '$2=="city"{printf("%s, ", $4)}$2=="region"{print $4}'
% var="$(curl ipinfo.io/"8.8.8.8" 2>/dev/null)"
% <<<"$var" awk -F'"' '$2=="city"{printf("%s, ", $4)}$2=="region"{print $4}'
Mountain View, California

但是,除非您想curl多次使用的输出,否则您可能只会使用管道:

curl ipinfo.io/"8.8.8.8" 2>/dev/null | awk -F'"' '$2=="city"{printf("%s, ", $4)}$2=="region"{print $4}'
curl ipinfo.io/"8.8.8.8" 2>/dev/null | awk -F'"' '$2=="city"{printf("%s, ", $4)}$2=="region"{print $4}'
Mountain View, California

<<<是一种称为“此处字符串”的输入重定向形式;它将命令的 STDIN 从终端重定向到字符串。

这里发生的情况是,$var在双引号之间扩展;AWK 命令的 STDIN 从终端重定向到扩展的字符串,然后 AWK 将该字符串读取为它的输入文件。

答案2

我希望将数据卷入 shell 脚本变量中,然后使用 cat 或 awk 对该变量进行操作,就像它是一个文件一样。这可行吗,或者有解决方法吗?

当然可以。如果内容不是太大,并且您想要运行多个命令来解析内容,那么将其缓存在内存中而不是每次都重新下载是件好事。

将结果存储curl在变量中:

ipinfo=$(curl ipinfo.io/8.8.8.8)

要在其上运行命令:

<<< "$ipinfo" awk ...
<<< "$ipinfo" sed ...

双引号“$ipinfo”对于保留所有空格字符很重要。

不将内容保存在变量中的“解决方法”是找出一种在单个管道中处理内容的方法,例如@kos做过。

答案3

另一种更简单、更易读的方法是,你可以使用python存在于所有基于 Linux 的系统中,为你解析 json

简单地说,导入jsonsys包来加载json对象,然后从对象打印result您需要的任何属性:

curl ipinfo.io/"8.8.8.8" 2>/dev/null | 
  python -c 'import  json,sys; 
             result=json.load(sys.stdin); 
             print(result["'city'"] + ", " + result["'region'"])';

我以更易读的方式添加了脚本,但是\如果您需要将其写在多行中,则应该将其放在一行中或在每行末尾添加。

答案4

由于输出curl将是 JSON,因此适当/更简单的工具似乎是jq(轻量级且灵活的命令行 JSON 处理器):

$ curl ipinfo.io/"1.1.1.1" 2>/dev/null | jq --raw-output '"\(.city), \(.region)"'
White Hall, Alabama

相关内容