grep 和 tail -f 用于 UTF-16 二进制文件 - 尝试使用简单的 awk
grep and tail -f for a UTF-16 binary file - trying to use simple awk
我怎样才能达到:
tail -f file.txt | grep 'regexp'
仅输出与正则表达式匹配的缓冲行,例如来自文件类型的 'Result'
:
$ file file.txt
file.txt:Little-endian UTF-16 Unicode text, with CRLF line terminators
下面的 tail -f
流内容转换为 utf-8
的示例:
Package end.
Total warnings: 40
Total errors: 0
Elapsed time: 24.4267192 secs.
...Package Executed.
Result: Success
Awk?
管道传输到 grep
的问题让我想到了 awk
作为去除违规字符并从正则表达式生成匹配行的即时解决方案。
awk
似乎给出了最有希望的结果,但是,我发现它 return 是整个流而不是单独的匹配行:
tail -f file.txt | awk '{sub("/[^\x20-\x7F]/", "");/Result/;print}'
Package end.
Total warnings: 40
Total errors: 0
Elapsed time: 24.4267192 secs.
...Package Executed.
Result: Success
我试过的
正在将流和管道转换为 grep
tail -f file.txt | iconv -t UTF-8 | grep 'regexp'
使用 luit
根据 this post 更改终端编码
luit -encoding UTF-8 -- tail -f file.txt | grep 'regexp'
删除非 ASCII
个字符,described here,然后传送到 grep
tail -f file.txt | tr -d '[^\x20-\x7F]' | grep 'regexp'
tail -f file.txt | sed 's/[^\x00-\x7F]//' | grep 'regexp'
上述使用grep
标志的各种组合--line-buffered
、-a
以及sed -u
- 在上面
之前使用luit -encoding UTF-8 --
- 使用包含
grep -f
正则表达式的相同编码的文件
为什么他们失败了
- 大多数尝试,根本没有任何内容打印到屏幕上,因为
grep
搜索 'regexp'
而实际上文本类似于 '\x00r\x00e\x00g\x00e\x00x\x00p'
- 例如 'R'
将 return 行 'Result: Success'
但 'Result'
不会
- 如果一个完整的正则表达式得到匹配,例如在使用
grep -f
的情况下,它将 return 整个流并且似乎不只是 return匹配行
- 通过
sed
或 tr
或 iconv
的管道似乎断开了通往 grep
的管道,而 grep
似乎仍然只能匹配个人字符
编辑
我使用 xxd
查看了 utf-16
格式的原始文件,目的是使用正则表达式来匹配编码,它给出了以下输出:
$ tail file.txt | xxd
00000000: 0050 0061 0063 006b 0061 0067 0065 0020 .P.a.c.k.a.g.e.
00000010: 0065 006e 0064 002e 000d 000a 000d 000a .e.n.d..........
00000020: 0054 006f 0074 0061 006c 0020 0077 0061 .T.o.t.a.l. .w.a
00000030: 0072 006e 0069 006e 0067 0073 003a 0020 .r.n.i.n.g.s.:.
00000040: 0034 0030 000d 000a 0054 006f 0074 0061 .4.0.....T.o.t.a
00000050: 006c 0020 0065 0072 0072 006f 0072 0073 .l. .e.r.r.o.r.s
00000060: 003a 0020 0030 000d 000a 0045 006c 0061 .:. .0.....E.l.a
00000070: 0070 0073 0065 0064 0020 0074 0069 006d .p.s.e.d. .t.i.m
00000080: 0065 003a 0020 0032 0034 002e 0034 0032 .e.:. .2.4...4.2
00000090: 0036 0037 0031 0039 0032 0020 0073 0065 .6.7.1.9.2. .s.e
000000a0: 0063 0073 002e 000d 000a 002e 002e 002e .c.s............
000000b0: 0050 0061 0063 006b 0061 0067 0065 0020 .P.a.c.k.a.g.e.
000000c0: 0045 0078 0065 0063 0075 0074 0065 0064 .E.x.e.c.u.t.e.d
000000d0: 002e 000d 000a 000d 000a 0052 0065 0073 ...........R.e.s
000000e0: 0075 006c 0074 003a 0020 0053 0075 0063 .u.l.t.:. .S.u.c
000000f0: 0063 0065 0073 0073 000d 000a 000d 000a .c.e.s.s........
00000100: 00
适用于 Cygwin 的最草率的解决方案是修复您的 awk
语句:
tail -f file.txt | \
LC_CTYPE=C awk '{ gsub("[^[:print:]]", ""); if([=10=] ~ /Result/) print; }'
这有一些相互抵消的错误,例如 tail
在尴尬的地方切割 UTF-16LE 文件,但 awk
剥离我们希望是垃圾的东西。
一个可靠的解决方案可能是:
tail -c +1 -f file.txt | \
script -qc 'iconv -f UTF-16LE -t UTF-8' /dev/null | grep Result
但它会读取整个文件,我不知道 Cygwin 使用 script
说服 iconv
不要缓冲(它会在 GNU/Linux 上工作)的效果如何。
我发现一个简单的正则表达式可以忽略搜索字符串中字母之间的任何字符...
这匹配 'Result'
同时允许每个字母之间有任何一个字符...
$ tail -f file.txt | grep -a 'R.e.s.u.l.t'
Result: Success
$ tail -f file.txt | awk '/R.e.s.u.l.t./'
Result: Success
或根据 :避免输入所有繁琐的点...
search="Result"
tail -f file.txt | grep -a -e "$(echo "$search" | sed 's/./&./g')"
我怎样才能达到:
tail -f file.txt | grep 'regexp'
仅输出与正则表达式匹配的缓冲行,例如来自文件类型的 'Result'
:
$ file file.txt
file.txt:Little-endian UTF-16 Unicode text, with CRLF line terminators
下面的 tail -f
流内容转换为 utf-8
的示例:
Package end.
Total warnings: 40
Total errors: 0
Elapsed time: 24.4267192 secs.
...Package Executed.
Result: Success
Awk?
管道传输到 grep
的问题让我想到了 awk
作为去除违规字符并从正则表达式生成匹配行的即时解决方案。
awk
似乎给出了最有希望的结果,但是,我发现它 return 是整个流而不是单独的匹配行:
tail -f file.txt | awk '{sub("/[^\x20-\x7F]/", "");/Result/;print}'
Package end.
Total warnings: 40
Total errors: 0
Elapsed time: 24.4267192 secs.
...Package Executed.
Result: Success
我试过的
正在将流和管道转换为 grep
tail -f file.txt | iconv -t UTF-8 | grep 'regexp'
使用
luit
根据 this post 更改终端编码luit -encoding UTF-8 -- tail -f file.txt | grep 'regexp'
删除非
ASCII
个字符,described here,然后传送到grep
tail -f file.txt | tr -d '[^\x20-\x7F]' | grep 'regexp' tail -f file.txt | sed 's/[^\x00-\x7F]//' | grep 'regexp'
上述使用
grep
标志的各种组合--line-buffered
、-a
以及sed -u
- 在上面 之前使用
- 使用包含
grep -f
正则表达式的相同编码的文件
luit -encoding UTF-8 --
为什么他们失败了
- 大多数尝试,根本没有任何内容打印到屏幕上,因为
grep
搜索'regexp'
而实际上文本类似于'\x00r\x00e\x00g\x00e\x00x\x00p'
- 例如'R'
将 return 行'Result: Success'
但'Result'
不会 - 如果一个完整的正则表达式得到匹配,例如在使用
grep -f
的情况下,它将 return 整个流并且似乎不只是 return匹配行 - 通过
sed
或tr
或iconv
的管道似乎断开了通往grep
的管道,而grep
似乎仍然只能匹配个人字符
编辑
我使用 xxd
查看了 utf-16
格式的原始文件,目的是使用正则表达式来匹配编码,它给出了以下输出:
$ tail file.txt | xxd
00000000: 0050 0061 0063 006b 0061 0067 0065 0020 .P.a.c.k.a.g.e.
00000010: 0065 006e 0064 002e 000d 000a 000d 000a .e.n.d..........
00000020: 0054 006f 0074 0061 006c 0020 0077 0061 .T.o.t.a.l. .w.a
00000030: 0072 006e 0069 006e 0067 0073 003a 0020 .r.n.i.n.g.s.:.
00000040: 0034 0030 000d 000a 0054 006f 0074 0061 .4.0.....T.o.t.a
00000050: 006c 0020 0065 0072 0072 006f 0072 0073 .l. .e.r.r.o.r.s
00000060: 003a 0020 0030 000d 000a 0045 006c 0061 .:. .0.....E.l.a
00000070: 0070 0073 0065 0064 0020 0074 0069 006d .p.s.e.d. .t.i.m
00000080: 0065 003a 0020 0032 0034 002e 0034 0032 .e.:. .2.4...4.2
00000090: 0036 0037 0031 0039 0032 0020 0073 0065 .6.7.1.9.2. .s.e
000000a0: 0063 0073 002e 000d 000a 002e 002e 002e .c.s............
000000b0: 0050 0061 0063 006b 0061 0067 0065 0020 .P.a.c.k.a.g.e.
000000c0: 0045 0078 0065 0063 0075 0074 0065 0064 .E.x.e.c.u.t.e.d
000000d0: 002e 000d 000a 000d 000a 0052 0065 0073 ...........R.e.s
000000e0: 0075 006c 0074 003a 0020 0053 0075 0063 .u.l.t.:. .S.u.c
000000f0: 0063 0065 0073 0073 000d 000a 000d 000a .c.e.s.s........
00000100: 00
适用于 Cygwin 的最草率的解决方案是修复您的 awk
语句:
tail -f file.txt | \
LC_CTYPE=C awk '{ gsub("[^[:print:]]", ""); if([=10=] ~ /Result/) print; }'
这有一些相互抵消的错误,例如 tail
在尴尬的地方切割 UTF-16LE 文件,但 awk
剥离我们希望是垃圾的东西。
一个可靠的解决方案可能是:
tail -c +1 -f file.txt | \
script -qc 'iconv -f UTF-16LE -t UTF-8' /dev/null | grep Result
但它会读取整个文件,我不知道 Cygwin 使用 script
说服 iconv
不要缓冲(它会在 GNU/Linux 上工作)的效果如何。
我发现一个简单的正则表达式可以忽略搜索字符串中字母之间的任何字符...
这匹配 'Result'
同时允许每个字母之间有任何一个字符...
$ tail -f file.txt | grep -a 'R.e.s.u.l.t'
Result: Success
$ tail -f file.txt | awk '/R.e.s.u.l.t./'
Result: Success
或根据
search="Result"
tail -f file.txt | grep -a -e "$(echo "$search" | sed 's/./&./g')"