不可打印的字符未被识别为字段分隔符
Posted
技术标签:
【中文标题】不可打印的字符未被识别为字段分隔符【英文标题】:non-printable character not recognised as field separator 【发布时间】:2019-06-05 23:21:59 【问题描述】:我有一个文件。它的字段分隔符是不可打印的字符\x1c
(Python 中的chr(28)
)。在 VI 中,它看起来像 a^\b^\c
,但使用 cat
我只看到 abc
。没有看到字段分隔符^\
。
我有一个简单的 awk 命令:
awk -F $’\x1c’ ‘print NF’ a
获取字段总数。它适用于 MacOS,但在 AIX 上却失败了。 AIX 似乎无法识别字段分隔符。所以输出是1
,这意味着整行被认为是一个字段。
如何在 AIX 上执行此操作?任何想法都非常感谢。
【问题讨论】:
创建test.py来准备数据 Python 代码:print('a'+chr(28)+'b'+chr(28)+'c' 不是awk
-特定的;使用 bash
而不是默认的 AIX-shell (ksh
)。或者像这样使用printf
:FldSep=$(printf '\034'); awk -F "$FldSep" ...
@LorinczyZsigmond 我必须使用 ksh。谢谢你的第二种方式有效。我不明白的一件事。你使用 \034 。是八进制数吗?我试过 FldSep=$(printf ‘\xc1’ );为什么不行?
您是否尝试在 AIX 中使用 gawk(如果已安装)?
【参考方案1】:
我能够在运行 ksh 的 SOLARIS 上重现这一点。
sol bash $ printf '\034a\034b\034c' | cat -v
^\a^\b^\c$
sol bash $ printf '\034a\034b\034c' | awk -F$'\x1c' 'print NF'
4
sol bash $ printf '\034a\034b\034c' | awk -F$'\034' 'print NF'
4
sol ksh $ printf '\034a\034b\034c' | cat -v
^\a^\b^\c$
sol ksh $ printf '\034a\034b\034c' | awk -F$'\x1c' 'print NF'
1
sol ksh $ printf '\034a\034b\034c' | awk -F$'\034' 'print NF'
1
我无法确认这是 ksh 问题还是 awk 问题,因为其他情况都失败了。
sol ksh/bash $ printf '\034a\034b\034c' | awk 'BEGINFS="\034"print NF'
1
以上所有案例都可以在任何 Linux 系统(默认运行 GNU awk)上成功运行,但似乎失败了。
以下技巧是一个完全不会失败的工作方法(直到它会失败):
sol ksh/bash $ printf '\034a\034b\034c' | awk 'BEGINFS=sprintf("%c",28)print NF'
4
上述工作是因为我们让 awk 使用 sprintf
函数设置 FS,其中我们传递十进制数 28=x1c=034
【讨论】:
【参考方案2】:$'\x1c'
是一个 bashizm, 可移植格式是 "$(printf '\034')"
。
(这个答案已经写成评论了。)
【讨论】:
【参考方案3】:当awk
有问题时,试试 Perl
$ cat -vT tonyren.txt
a^\b^\c^\d
p^\q^\r^\s
x^\y^\z
$ perl -F"\x1c" -le ' print scalar @F ' tonyren.txt
4
4
3
$
【讨论】:
可以加hexdump file
不,awk 没有sometimes break portability
。 awk 有版本,就像 perl 一样,并且特定于版本的扩展只适用于指定的版本,仅此而已。如果您编写 POSIX awk 代码,那么它可以在大多数兼容 POSIX 的 awk 中工作,并且它的好处是每个 UNIX 安装都安装了 awk,而只有一些安装了 perl。
对于这个问题,我认为它在 awk 中没有特定于版本的问题。也许我会改写它。正如 Marck Setchell 在他的 cmets 中提到的,Perl 是处理这种情况的方法。Perl 带有所有 *nix 风格,在企业版中,安装 CPAN 模块可能会被禁用。以上是关于不可打印的字符未被识别为字段分隔符的主要内容,如果未能解决你的问题,请参考以下文章
SQLite 和 .net 字符串未被识别为有效的 DateTime
尝试使用linq过滤数据时,字符串未被识别为有效的DateTime