不可打印的字符未被识别为字段分隔符

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)。或者像这样使用printfFldSep=$(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

字符串未被识别为有效的日期时间[关闭]

JSON.NET:字符串 '7/1/20 14:15' 未被识别为有效的 DateTime

字符串格式未被识别为有效的日期时间格式[关闭]