我正在尝试使用以下命令监视主题更改:
dbus-monitor --session "interface='org.freedesktop.portal.Settings', member=SettingChanged" | grep -o "uint32 ."
Run Code Online (Sandbox Code Playgroud)
现在的输出看起来像这样:
uint32 0
uint32 0
uint32 1
uint32 1
uint32 0
uint32 0
uint32 1
uint32 1
Run Code Online (Sandbox Code Playgroud)
此输出来自主题切换。由于某种原因,主题通知显示两次。现在我想将其通过管道传输到uniq
,因此我只保留一个条目,如下所示:
uint32 0
uint32 1
uint32 0
uint32 1
Run Code Online (Sandbox Code Playgroud)
然而,uniq
在最后追加不会再产生任何输出。
uint32 0
uint32 0
uint32 1
uint32 1
uint32 0
uint32 0
uint32 1
uint32 1
Run Code Online (Sandbox Code Playgroud)
从man uniq
:
从 INPUT(或标准输入)中过滤相邻的匹配行,写入 OUTPUT(或标准输出)。
uniq
需要缓冲至少最后一个输出行才能检测相邻行,我看不出有任何原因它不能缓冲它并沿着管道传递它。我已经尝试按照此处的建议调整行缓冲,但结果对我来说仍然相同。
uint32 0
uint32 1
uint32 0
uint32 1
Run Code Online (Sandbox Code Playgroud)
A.B*_*A.B 27
这是许多工具的常见行为,继承自带有操作I/O 流的函数的默认标准 C 库行为(fopen(3)
, fwrite(3)
...)。这已记录在setvbuf(3)
(或已弃用的变体)中。几个 *nixes 都说了同样的话: * BSD 、 Solaris 、 GNU / Linux ...,但POSIX没有指定它,并且 ISO/IEC 9899 太难以捉摸。GNU 告诉:
新打开的流通常是完全缓冲的,但有一个例外:连接到交互式设备(例如终端)的流最初是行缓冲的。
(此外,stderr在所有实现中通常都是无缓冲的。这对于这个 Q/A 来说并不重要。)
因此,对于大多数文本过滤命令(并非全部,例如cat
没有此行为),只要它不是管道中的最后一个命令,其输出就不再进行行缓冲,并且换行不会触发立即发送数据下一个要处理的命令。
这里相关命令不是uniq
butgrep
,因为它的输出从终端切换到非终端。GNUgrep
有一个选项可以改变这种行为--line-buffered
::
--line-buffered
在输出上使用行缓冲。这可能会导致性能损失。
如果该命令没有特定的选项来选择行为,人们仍然可以使用通过机制stdbuf
来改变行为的命令。要恢复不在管道末尾的命令的行缓冲行为,可以为该命令添加前缀.setvbuf(3)
LD_PRELOAD
stdbuf -oL
对于OP的情况:
dbus-monitor --session "interface='org.freedesktop.portal.Settings', member=SettingChanged" |
grep --line-buffered -o "uint32 ." | uniq
Run Code Online (Sandbox Code Playgroud)
或者如果此grep
命令也没有特定选项:
dbus-monitor --session "interface='org.freedesktop.portal.Settings', member=SettingChanged" |
stdbuf -oL grep -o "uint32 ." | uniq
Run Code Online (Sandbox Code Playgroud)
请注意,在这两种情况下,uniq
处于管道末端不需要对其默认行为进行任何调整。
如果稍后管道被扩充并且uniq
不再位于末端,从而不再输出到终端,它也会改变行为并且需要相同的处理。例如,命令uniq
在终端上单独的行缓冲行为:
uniq
Run Code Online (Sandbox Code Playgroud)
更改为全缓冲:
uniq | cat
Run Code Online (Sandbox Code Playgroud)
但可以通过以下方式反转为行缓冲:
stdbuf -oL uniq | cat
Run Code Online (Sandbox Code Playgroud)