微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

gawk FS将记录分成单个字符

如果字段分隔符是空字符串,则每个字符将成为单独的字段
$echo hello | awk -F '' -v OFS=,'{$1 = NF OFS $1} 1'
5,h,e,l,o

但是,如果FS是可能匹配零次的正则表达式,则不会发生相同的行为:

$echo hello | awk -F ' *' -v OFS=,'{$1 = NF OFS $1} 1'
1,hello

谁知道为什么会这样?我在gawk manual中找不到任何东西.FS =“”只是一个特例吗?

我最感兴趣的是理解为什么第二种情况不会将记录分成更多的字段.好像awk正在处理FS =“*”,如FS =“”

解决方法

有趣的问题!

我刚刚提取了gnu-awk 4.1.0的代码,我想我们可以在文件field.c中找到答案.

line 371:
 * re_parse_field --- parse fields using a regexp.
 *
 * This is called both from get_field() and from do_split()
 * via (*parse_field)().  This variation is for when FS is a regular
 * expression -- either user-defined or because RS=="" and FS==" "
 */
static long
re_parse_field(lo...

这一行:(第425行):

if (REEND(rp,scan) == RESTART(rp,scan)) {   /* null match */

这里是您的问题中< space> *匹配的情况.实现没有增加nf,也就是说,它认为整行是一个单独的字段.注意这个函数也用在do_split()函数中.

首先,如果FS为空字符串,则gawk将每个字符分隔为其自己的字段. gawk的doc清楚地写了这个,也在代码中,我们可以看到:

line 613:
 * null_parse_field --- each character is a separate field
 *
 * This is called both from get_field() and from do_split()
 * via (*parse_field)().  This variation is for when FS is the null string.
 */
static long
null_parse_field(long up_to,

如果FS有单个字符,awk不会将其视为正则表达式.这也在doc中提到过.也在代码中:

#line 667
 * sc_parse_field --- single character field separator
 *
 * This is called both from get_field() and from do_split()
 * via (*parse_field)().  This variation is for when FS is a single character
 * other than space.
 */
static long
sc_parse_field(l

如果我们读取函数,那里就没有进行正则表达式匹配处理.

函数re_parse_field()和sc_parse_field()的注释中,我们看到do_split也会调用它们.它解释了为什么我们在以下命令中有1而不是3:

kent$ echo "foo"|awk '{split($0,a,/ */);print length(a)}'
1

注意,为了避免使帖子过长,我没有在这里粘贴完整的代码,我们可以在这里找到代码

http://git.savannah.gnu.org/cgit/gawk.git/

原文地址:https://www.jb51.cc/linux/393125.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐