如果我有一个脚本,可以为它处理的每个文件将不同的数据类型发送到 STDOUT。如何分离每种数据类型,以便读取 STDIN 的另一个脚本知道哪个是什么?
例如。我有一个脚本,它为它处理的每个文件生成两个不同的(未知)字符串和两个不同的(未知)数字。然后还有另一个脚本从 STDIN 读取来处理每个给定的字符串、数字。如何格式化第一个脚本的输出,以便可以使第二个脚本正确识别每种类型?
我习惯于通过 JSON 序列化数据,用于网络,但我想知道是否有更轻量级或内置的 STDIN/STDOUT 解决方案?也许一些独特的分隔符或我缺少的东西?
你没有解释你的标准输出是什么以及它去哪里了!(例如,CGI应用程序的标准输出 -间接地 - 到某些浏览器)。
在Unix哲学和Unix的管道要stdin和stdout是纯文本,但是这仅仅是一个惯例。在某些情况下,您可以有其他约定(例如lpr或lp通常更喜欢标准输入上的 PDF)。
如果您正在编写某个程序,您可能会使其具有某种模式(例如由某个程序参数指定)来输出更多结构化的文本,例如 JSON 或 XML 或CSV或YAML。注意jq可以处理 JSON。
某些程序检测(使用isatty和/或fstat)它们的stdout(或它们的stdin)何时是终端并相应地采取行动(可能通过使用ncurses、termios或ANSI 转义码)。
许多文本格式(尤其是 XML)具有传统的起始字符或标题,因此在某些情况下猜测它们(即找出文件格式)是可能的。还要查看MIME 和libmagic(以及file(1))。
我有一个脚本,它为它处理的每个文件生成两个不同的(未知)字符串和两个不同的(未知)数字。然后还有另一个脚本从 STDIN 读取来处理每个给定的字符串、数字。如何格式化第一个脚本的输出,以便可以使第二个脚本正确识别每种类型?
如果你知道(和文件)的未知字符串是足够好的不包含控制字符,如换行符(这样它们每一个都是单独的线),你可以决定像一些格式
FIRSTSTRING: 第一个字符串
FIRSTNUMBER: 第一个号码
例如
FIRSTSTRING: foo bar is nice!
FIRSTNUMBER: 42
Run Code Online (Sandbox Code Playgroud)
然后为您的第二个脚本编写并使用一些简单的awk脚本(或者可能使用sed)
换句话说,决定并记录一个简单的临时格式;在您的情况下,这可能比 JSON 更易于处理。您可以拥有自己的临时约定,前提是您对其进行了记录(可能使用了一些EBNF符号)。
很多工具都准备好了;例如ps、ls、df和ifconfig具有临时但有据可查的输出格式和约定。对于proc(5)也是如此。因此,许多脚本可以解析这样的输出。
但是,JSON 被设计为简单、灵活、可扩展、可扩展……并且它能够表示任意字符串(即使是控制字符、多行等……)。如果这对您很重要,请使用它。
可以重新发明并重新实现所有 Unix 实用程序以输出例如 JSON 或 XML(但这样做需要大量工作)。例如,有些人重新发明了proc(5)并制作了一个内核模块,使其具有/xmlproc/伪文件系统,而不/proc/是以某种 XML 形式输出系统内核数据的系统。但这并不成功!社会习俗很重要(这就是为什么记录您的输出格式如此重要,至少在长评论中)。
(即使您使用 JSON 或 XML,您也需要记录如何使用它们)
顺便说一句,许多现有的 Unix 工具可能会在约定中添加微妙之处。例如,文件路径中的空格或制表符或返回字符是可能的(请参阅path_resolution(7)),但可能会令人皱眉(所以我从不这样做)。$HOME某些用户的目录理论上可以包含返回字符或冒号,但如果这样做,大多数工具都会受到影响(并且您可能会破坏passwd(5) ...)。以破折号开头的文件路径是不友好的,很长的路径也是如此(例如$HOME,理论上你可能有 3000 个字符,但这真的很不明智)。
您有两个脚本,一个生成两个字符串和两个数字。您可以在第二个脚本中将其解析为两个字符串和两个数字。
由于这两个脚本都在您的控制之下,您可以以任何方便第二个脚本读取数据的方式自由地将数据从一个脚本发送到另一个脚本。
由您决定在两个脚本之间传送的数据的格式、顺序和解释。如果这对您有意义,您甚至可以发送二进制编码数据。
除了您通过决定两个脚本或程序之间的特定“合同”或“协议”来弥补自己的数据类型之外,没有可应用于数据的数据类型。
一些标准的 Unix 工具喜欢sort并cut假设输入是特定格式的,但可以通过使用命令行选项来改变它们对输入数据的解释。
人为的例子:
#!/bin/sh
echo 'first string'
echo 'second string'
echo '1.1'
echo '3.14'
Run Code Online (Sandbox Code Playgroud)
然后第二个脚本读取:
#!/bin/sh
IFS= read -r string1
IFS= read -r string2
read number1 number2
Run Code Online (Sandbox Code Playgroud)
或者,使用 JSON:
#!/bin/sh
echo '{ "string1": "hello", "string2": "world", "numbers": [1.1,3.14] }'
Run Code Online (Sandbox Code Playgroud)
第二个脚本:
#!/bin/sh
jq -r '"A number: \(.numbers[])"'
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1110 次 |
| 最近记录: |