在 psql 中的 table 条记录之间画线

Draw line between table records in psql

假设我正在从 psql 中查询 table,如下所示:

select * from sometable ;

根据我当前的设置,我会得到这样的结果:

+-----------------------------+
| column1 | column2 | column3 |
+---------+---------+---------+
|  value  |  value  |  value  |
|  value  |  value  |  value  |
|  value  |  value  |  value  |
+---------+---------+---------+

因为我经常与非信息学领域的人分享交互式 psql shell(我需要在其中即时查询),出于可读性原因,我想要这样的输出:

+-----------------------------+
| column1 | column2 | column3 |
+---------+---------+---------+
|  value  |  value  |  value  |
+---------+---------+---------+
|  value  |  value  |  value  |
+---------+---------+---------+
|  value  |  value  |  value  |
+---------+---------+---------+

也就是说,我希望每条记录之间有一条线,因为当我显示 长文本值 并且它们 包装 (小提示:使用 \pset format wrapped 获得此包装),可能很难区分 不同的记录。

你知道如何在 psql 上实现这个吗?我尝试了不同的选项,例如设置 recordsep 字符,但没有成功。

正如我在上面的评论中提到的,这并没有直接回答问题,在日常工作流程中可能不是很好的解决方案。


在控制台中显示结果的替代方法是在浏览器中显示它们。

使用\H(或psql --html)显示:

# \H                   -- use \H to toggle back to normal mode
Output format is html.

# SELECT * FROM sometable ;
<table border="1">
  <tr>
    <th align="center">column1</th>
    <th align="center">column2</th>
    <th align="center">column3</th>
  </tr>
  <tr valign="top">
    <td align="left">value</td>
    <td align="left">value</td>
    <td align="left">value</td>
  </tr>
  <tr valign="top">
    <td align="left">value</td>
    <td align="left">value</td>
    <td align="left">value</td>
  </tr>
  <tr valign="top">
    <td align="left">value</td>
    <td align="left">value</td>
    <td align="left">value</td>
  </tr>
</table>
<p>(3 rows)<br />
</p>

我们可以使用 \g | 将其通过管道传输到另一个程序。然而,管道到浏览器似乎有点挑剔,所以对我来说使用临时文件似乎更容易(请注意,可能有更好的方法来做到这一点):

使用脚本(我使用 /tmp/pipe_to_browser.sh,您可能希望将其设置在 PATH 中的某处),例如

#!/bin/sh

tmpfile=$(mktemp --suffix=.html)
cat - > $tmpfile

# Could use a specific browser too, eg `firefox`, if `x-www-browser` does not exist on your system
x-www-browser $tmpfile
# SELECT * FROM sometable \g | /tmp/pipe_to_browser.sh

打开一个新标签显示类似
的内容

多亏了 answer by Marth,我找到了一种方法来获得准确的输出。

配置

我在答案末尾创建了一个 Python 脚本。

我给它取了一个简称,我叫它ftab(花哨的table)。

该脚本仅检测 table 中存在的一条水平线(默认情况下总是至少有一条,介于 headers 和值之间)并在每条记录后打印该水平线。

输出的最后两行按原样打印,因为在默认设置下,最后两行只是总结记录总数的一行和一个空行。

脚本可以方便地存放在PATH环境变量中包含的文件夹中,并且可以将其设为executable,例如来自 运行宁:

chmod +x ftab

我还建议您制作脚本文件non-writeable,否则如果您忘记在查询中输入管道符号|,您可能会不小心覆盖它并丢失代码。

chmod -w ftab

一种使用方法

现在,如果我执行查询但我或我的同事认为输出 table 的可读性不够,我可以输入:

\g | ftab

并再次执行相同的查询,但 table 的输入与问题中的解释完全相同,即

+---------+---------+---------+
| column1 | column2 | column3 |
+---------+---------+---------+
|  value  |  value  |  value  |
+---------+---------+---------+
|  value  |  value  |  value  |
+---------+---------+---------+
|  value  |  value  |  value  |
+---------+---------+---------+
(3 rows)

另一种使用方式

如果我愿意,我总能看到这样的 table 而不是默认方式。

为了做到这一点,我只是在每个查询的末尾附加 \g | ftab

例如:

select * from sometable \g | ftab

如果你需要滚动

如果有很多记录并且您需要滚动,只需像在终端中那样附加 | less,例如

select * from sometable \g | ftab | less

编辑(支持包装值)

既然我说过这个特性在某些列中的值被多行包裹的情况下特别有用,我意识到我的第一个版本的 Python 脚本不能正确支持这种情况,所以我更新了。

特别是,我修改了脚本,添加了一个检查以查看一个值是否包含在多行中,这通常通过使用 . 终止列中的字符串来表示(如果该行是因为它太长而被打破)或 +(以防因为有换行符而被打破)。

因此,为了完全支持输出被包裹的情况,您需要:

  1. 通过键入启用换行:

    \pset format wrapped

  2. 由于使用了管道,无法再检测到屏幕宽度,因此您必须根据列数来决定宽度(出于某种原因,它必须至少为 70 列)。在我的例子中,我意识到我的屏幕通常是 210 列宽,所以我输入:

    \pset columns 210

当然,我需要在会议开始前设置这些命令,以便我准备好在会议开始时只 运行 查询。 :)

ftabPython脚本

#!/usr/local/bin/python3                                                                                                                                                                                                 

import sys

def outwrite(s):
  try:
    sys.stdout.write(s)
  except BrokenPipeError:
    exit(0)

rule=''
rulechars=set('|+-\n')

result = sys.stdin.readlines()

for line in result[:-2]:
  if set(line) <= rulechars:
    if rule == '':
      rule = line
      outwrite(rule)
  else:
    outwrite(line)
    if not any(x in line for x in ['.|', '.\n', '+|', '+\n']):
      outwrite(rule)

outwrite(result[-2])
outwrite(result[-1])

现在我找到了更好的答案,仍在 and on .

的基础上

这是使用这种方法的查询结果示例(有敏感数据,所以我用 X 字母替换了大部分字符)。

我认为这是理想的,比我以前的回答更容易使用和更可靠。

它也部分类似于 Marth 的回答,但主要区别在于不需要 GUI 浏览器,并且所有内容都在执行 psql 的同一终端中。

先决条件

首先你需要安装w3m工具,它可以读取HTML页,也可以像寻呼机一样使用(如less,但特别支持HTML).

在许多 Linux 发行版中,您只需键入以下内容即可安装它:

sudo apt install w3m

第一种方法(即时)

动态执行此操作的一种方法是在 SQL 命令末尾添加 \H \g | w3m -T text/html\H 启用 HTML 输出,其余命令将输出通过管道传输到 w3m 工具。

例如这样的命令:

select * from sometable \H \g | w3m -T text/html

会产生这样的结果:

┌───────┬───────┬───────┐
│column1│column2│column3│
├───────┼───────┼───────┤
│ value │ value │ value │
├───────┼───────┼───────┤
│ value │ value │ value │
├───────┼───────┼───────┤
│ value │ value │ value │
└───────┴───────┴───────┘
(3 rows)

你也可以先得到一个正常的输出,然后决定你想让它更具可读性,然后你只需要输入:

\H \g | w3m -T text/html

并重复最后一个查询,但通过管道传输到 w3m。

您可以在看到 table 后再次键入 \H 来禁用 HTML 输出。

第二种方法(默认寻呼机)

您还可以通过将 w3m 设置为默认寻呼机来避免向 SQL 命令附加任何内容。

特别是,如果您键入:

\H
\setenv PAGER 'w3m -T text/html'
\pset pager always

从现在开始,所有查询的输出都将通过管道传输到 w3m,而无需向 SQL 命令附加任何内容。

管道到 w3m 的好处

  • 精美且可读性强的输出。
  • 记录和列分开。
  • 比我最初的想法更可靠。
  • 完美支持长记录值和包装记录值(而不是我第一个想法的手动解决方法)。
  • 如果您调整 window 的大小,它会自动适应您的终端大小。
  • 支持使用鼠标滚动。

小技巧和我的个人配置

这是我想使用 w3m 输出时的配置。

\H
\setenv PAGER 'w3m -T text/html -o confirm_qq=false -no-mouse'
\pset pager always

所以我基本上使用了上面描述的第二种方法,但我也为w3m添加了额外的选项:

  • -o confirm_qq=false 以防止 w3m 在每次看到结果;

  • -no-mouse 禁用鼠标支持。虽然我有点喜欢用鼠标滚动,但这会阻止我选择和复制数据以将其粘贴到其他应用程序中,因此我更喜欢禁用它并使用 PgUpPgDown 来滚动。

最后的说明

这种方法产生的输出非常易读,特别是当 运行 与其他人(尤其是非开发人员)一起实时查询时非常好。

但在很多情况下,如果数据易于阅读and/or你不需要显示非常花哨的查询结果,下面的方法会非常可读并且更容易设置

\pset format wrapped
\pset border 2

这个不那么花哨,多行记录之间的区别可能不太清楚,因为记录之间没有画水平线,但在很多情况下这可能就足够了。