免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 18392 | 回复: 17
打印 上一主题 下一主题

awk的sub与gsub [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2007-07-22 18:14 |只看该作者 |倒序浏览
有如下文件a.log
1abc 2abc
3abc 4abc
5abc 6abc
(列之间是\t)
awk 'FS="\t" gsub(/a/,"A")' a.log 输出正确
但是
awk 'FS="\t" gsub(/a/,"A",$1)' a.log 输出不正确:
1Abc 2abc
3Abc 4Abc
5Abc 6Abc
察看:
awk 'FS="\t" gsub(/a/,"A",$1) {print $2}' a.log
发现只有2abc,与出现的错误一致。
但是同时
awk 'gsub(/a/,"A",$1)' a.log正确
awk 'FS="\t" sub(/a/,"A",$1)' a.log正确
感觉和FS=xxx有关系,可究竟是为什么呢?

论坛徽章:
0
2 [报告]
发表于 2007-07-22 20:39 |只看该作者
sub匹配第一次出现的,gsub匹配所有的,与sed 's//' 和sed 's//g'一致。

你试试这个就知道是什么原因了。awk 'FS="\t" {print $1}' a.log

论坛徽章:
1
荣誉会员
日期:2011-11-23 16:44:17
3 [报告]
发表于 2007-07-23 00:46 |只看该作者
awk默认的分隔域是空格, TAB, 所以你不需要指定FS的
/home/lee#echo '1abc 2abc
3abc 4abc
5abc 6abc'|awk '{sub(/a/,"A"0);print}'
1A0bc 2abc
3A0bc 4abc
5A0bc 6abc
/home/lee#echo '1abc 2abc
3abc 4abc
5abc 6abc'|awk '{gsub(/a/,"A"0);print}'
1A0bc 2A0bc
3A0bc 4A0bc
5A0bc 6A0bc
//g,指的是一行里所有的匹配

论坛徽章:
0
4 [报告]
发表于 2007-07-23 09:40 |只看该作者
这个问题颇有点古怪,FS的赋值方式明显不对,但执行的结果也很难理解!
为什么第一行能够执行正确,但第二行数据就出现问题,而且似乎还影响了OFS,奇怪!
期待高手!

awk 'FS="\t"  gsub(/a/,"A",$1)'执行结果

1Abc 2abc
3Abc    4Abc
5Abc    6Abc
第一行分隔符为空格,以下都是\t!

[ 本帖最后由 ruifox 于 2007-7-23 09:43 编辑 ]

论坛徽章:
8
摩羯座
日期:2014-11-26 18:59:452015亚冠之浦和红钻
日期:2015-06-23 19:10:532015亚冠之西悉尼流浪者
日期:2015-08-21 08:40:5815-16赛季CBA联赛之山东
日期:2016-01-31 18:25:0515-16赛季CBA联赛之四川
日期:2016-02-16 16:08:30程序设计版块每日发帖之星
日期:2016-06-29 06:20:002017金鸡报晓
日期:2017-01-10 15:19:5615-16赛季CBA联赛之佛山
日期:2017-02-27 20:41:19
5 [报告]
发表于 2007-07-23 09:48 |只看该作者
原帖由 ruifox 于 2007-7-23 09:40 发表
这个问题颇有点古怪,FS的赋值方式明显不对,但执行的结果也很难理解!
为什么第一行能够执行正确,但第二行数据就出现问题,而且似乎还影响了OFS,奇怪!
期待高手!

awk 'FS="\t"  gsub(/a/,"A",$1)'执行 ...

第一行FS="\t"以前域已经拆分好了
第二行行才按\t拆分,结果是非常相当的正常的

  1. Advanced Notes: Changing FS Does Not Affect the Fields

  2. According to the POSIX standard, awk is supposed to behave as if each record is split into fields at the time it is read. In particular, this means that if you change the value of FS after a record is read, the value of the fields (i.e., how they were split) should reflect the old value of FS, not the new one.

  3. However, many implementations of awk do not work this way. Instead, they defer splitting the fields until a field is actually referenced. The fields are split using the current value of FS! (d.c.) This behavior can be difficult to diagnose. The following example illustrates the difference between the two methods. (The sed18 command prints just the first line of /etc/passwd.)

  4.      sed 1q /etc/passwd | awk '{ FS = ":" ; print $1 }'

  5. which usually prints:

  6.      root

  7. on an incorrect implementation of awk, while gawk prints something like:

  8.      root:nSijPlPhZZwgE:0:0:Root:/:
复制代码

论坛徽章:
0
6 [报告]
发表于 2007-07-23 14:26 |只看该作者
按照waker给出的解释,如下代码:
awk '{FS="\t"; gsub(/a/,"A",$1);print $0,NF}' filename
确实能够工作,虽然FS赋值是无效的(awk默认tab分割)

但是如下代码:
awk 'FS="\t" gsub(/a/,"A",$1){print $0,NF}' filename
结果是错的。

他们的区别就是代码块的位置,以及是否用分号分隔。
因此我觉得问题仍然出在花括号和分号上面。虽然FS的赋值是失效的,但是应该不影响结果才是。

论坛徽章:
8
摩羯座
日期:2014-11-26 18:59:452015亚冠之浦和红钻
日期:2015-06-23 19:10:532015亚冠之西悉尼流浪者
日期:2015-08-21 08:40:5815-16赛季CBA联赛之山东
日期:2016-01-31 18:25:0515-16赛季CBA联赛之四川
日期:2016-02-16 16:08:30程序设计版块每日发帖之星
日期:2016-06-29 06:20:002017金鸡报晓
日期:2017-01-10 15:19:5615-16赛季CBA联赛之佛山
日期:2017-02-27 20:41:19
7 [报告]
发表于 2007-07-23 14:32 |只看该作者
如果没有特殊的设计
设置FS的传统位置是
BEGIN{.....FS=xxx...}

论坛徽章:
0
8 [报告]
发表于 2007-07-23 14:45 |只看该作者
。。好吧。
那这个就算
GNU Awk 3.1.1
的bug好了。。

论坛徽章:
1
荣誉会员
日期:2011-11-23 16:44:17
9 [报告]
发表于 2007-07-23 14:47 |只看该作者

  1. If you find a  bug  in  gawk,  please  send  electronic  mail  to  bug-
  2.        [email]gawk@gnu.org[/email].
复制代码

论坛徽章:
8
摩羯座
日期:2014-11-26 18:59:452015亚冠之浦和红钻
日期:2015-06-23 19:10:532015亚冠之西悉尼流浪者
日期:2015-08-21 08:40:5815-16赛季CBA联赛之山东
日期:2016-01-31 18:25:0515-16赛季CBA联赛之四川
日期:2016-02-16 16:08:30程序设计版块每日发帖之星
日期:2016-06-29 06:20:002017金鸡报晓
日期:2017-01-10 15:19:5615-16赛季CBA联赛之佛山
日期:2017-02-27 20:41:19
10 [报告]
发表于 2007-07-23 14:54 |只看该作者
原帖由 philonis 于 2007-7-23 14:45 发表
。。好吧。
那这个就算
GNU Awk 3.1.1
的bug好了。。

如果你是gawk ,你会如何处理?
条件{动作},这是awk基本方法,那么我们来看一个例子
$1==3{print }
如果awk在判断条件$1==3之前不进行域拆分,那么$1从什么地方来?
如果已经拆分过了,那么你的 FS=xx{...}只会在下一行起作用而不会在本行
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP