“ tail -f | iconv -fsjis”不输出任何内容


14

我想要tail -f一个文件,但是它的内容是sjis编码的,所以我需要将其转换为终端的本机(utf-8)编码。

当我做

尾-fx | iconv -fsjis

没有输出。如

尾x | iconv -fsjis

确实起作用,起初我以为这是一个缓冲问题,但是尝试unbufferstdbuf按照关闭管道中的缓冲中的描述进行操作并没有帮助。

实际上,即使将超过10k的数据添加到x中,也不会有输出,所以我想这不是一个缓冲问题(如果我没记错的话,缓冲区是4k),但是iconv仅在以下情况下才开始输出它收到一个EOF。

那么,如何尾部跟踪我的sjis编码文件?

Answers:


11

(用少许盐腌制)据我所知,问题出在libiconv工作方式上。多字节编码需要状态机对其进行解码,并且libiconv喜欢接收整个字符,因此您不能只在一个函数调用中给它一半字符,而在下一个函数调用中给另一个字符。

我可以想到另外两种解决方案,一种是好的带外方法,另一种是带内黑客。

更改终端仿真器编码(带外):一种方法是更改​​终端仿真器中的字符编码,因此其本机编码为Shift JIS。我刚刚检查了konsole,并对此表示支持。从菜单中,查看→字符编码→日语→sjis。然后tail -f,您可以只是文件,并且konsole将负责解码多字节字符并将其与字体字形匹配。

动态转码终端编码(带内;最佳):由Gilles提供,他让我想luit了很长时间。使用luit,它应该随XOrg发行版一起提供(在Debian中,它是package x11-utils)。像这样使用它:

$ luit -encoding SJIS -- tail -f x

这将使终端将SJIS与您的终端编码进行代码转换,然后运行tail -f x。缺点luit是它不支持所支持的大量编码libiconv。好处是几乎所有地方都可以使用它。

动态地对终端进行代码转换(带内;破解):这ttyconv是我多年前写的一种hack(最初是用C语言编写的,后来又用Python重做),用于libiconv对终端I / O进行代码转换。它产生一个新的伪终端,并且(a)将您键入的字符从本地编码转换为远程编码,并且(b)将您从远程编码接收的字符转换为本地编码。我用它来与使用标准Linux终端不支持的编码的服务器通信。请注意,我测试过的所有远程编码都是单字节编码,所以我不能保证它可以用于Shift JIS。这些天来,随着大多数系统切换到Unicode,我并不经常使用它。

这是您将如何使用它:

$ ttyconv -rsjis -- tail -f x

缺点ttyconv是我写了它,没有人使用它,但是我可能是个bug。我擅长这一点。好处是,它使用libiconv,因此,如果您的编码不正常,那是您最好的选择。最后,ttyconv --list支持100种编码。


很好,谢谢。带外对我不起作用(gnome-terminal,尽管它确实允许您更改编码),但是ttyconv就像一个魅力。
尤金·别列索夫斯基

2
如今,luit标准X11实用程序套件中有一部分与您的相似ttyconv
吉尔斯(Gillles)“所以-别再邪恶了”

@Gilles与之luit相似,不同之处在于它的工作原理比我的好得多。;) 谢谢!这就是为什么我一开始就停止使用的原因。自从我什至忘记了命令名以来的12年中,我一直在寻找它。
Alexios'4

@吉尔斯也luit为我工作。您为什么不将其设为“官方”答案?它是我的安装(debian)的一部分,因此对我来说最容易使用。
尤金·别列索夫斯基'04 -4-9

1
我更新了答案,使其luit成为SJIS的最佳选择。可悲的是,似乎它并不支持所有编码libiconv。看起来我仍然必须出于自己超现实的目的使用自己的解决方案。:)
Alexios

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.