免费注册 查看新帖 |

Chinaunix

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

[文本处理] 求助,awk调用shell命令时的变量和引号问题 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2019-01-29 22:09 |只看该作者 |倒序浏览
本帖最后由 zhxinling 于 2019-01-30 00:02 编辑

求助各位大神,在awk中调用shell命令,使用"cmd" | getline的方式,如果cmd命令中有单引号或调用awk变量时,应该怎么处理呢?
比如:我想在awk的END部分使用for循环调用shell中的date命令,返回一个时间序列的列表。
awk 'END{
    for(i=7;i>0;i--)
        {"date --date 'i day ago' +%Y-%m-%d" | getline date; array[i ]=date }
}'

其中标黄部分是在shell环境下的格式,使用到了单引号和i变量。正确的格式应该怎么写呢?

论坛徽章:
8
2016科比退役纪念章
日期:2018-10-24 08:24:0115-16赛季CBA联赛之北控
日期:2019-03-12 14:34:562016科比退役纪念章
日期:2019-04-01 10:33:0915-16赛季CBA联赛之山东
日期:2019-04-17 12:46:3215-16赛季CBA联赛之广夏
日期:2019-05-09 16:40:4015-16赛季CBA联赛之广夏
日期:2019-10-10 15:33:4015-16赛季CBA联赛之辽宁
日期:2019-10-15 08:37:0615-16赛季CBA联赛之北控
日期:2021-03-30 15:53:34
2 [报告]
发表于 2019-01-30 09:50 |只看该作者
引号套引号  肯定是要转义的,date命令里的单引号,可以改成转义的双引号\".
我觉得问题的关键还是  awk中的变量 i 怎么传递给 shell 命令中的字符串参数?肯定不能直接引用i,shell又不认的,也肯定不能用 $i, 在awk中表示的是字段啊。
我自己摸索了两个可能是笨办法的办法。

1. 调用的命令写在bash脚本里, 管道 前面调用命令时 把 i参数 传递给 bash脚本。
bash脚本这么写,保存为test.sh:
  1. date --date "$1 day ago" +%Y-%m-%d
复制代码

awk写法和结果如下:
  1. gawk 'END{for(i=7;i>0;i--){"bash test.sh " i|getline date;print date}}' file.txt
  2. 2019-01-23
  3. 2019-01-24
  4. 2019-01-25
  5. 2019-01-26
  6. 2019-01-27
  7. 2019-01-28
  8. 2019-01-29
复制代码


2.  先用sprintf()把 需要执行的shell命令格式化好,再管道前直接使用格式化好的shell命令。其中日期的格式化符%也要用%转义。
写法和结果如下:
  1. gawk 'END{for(i=7;i>0;i--){cmdstr=sprintf("date --date \"%s day ago \" +%%Y-%%m-%%d",i);cmdstr|getline date;print date}}' file.txt
  2. 2019-01-23
  3. 2019-01-24
  4. 2019-01-25
  5. 2019-01-26
  6. 2019-01-27
  7. 2019-01-28
  8. 2019-01-29
复制代码

论坛徽章:
0
3 [报告]
发表于 2019-01-30 14:53 |只看该作者
提示: 作者被禁止或删除 内容自动屏蔽

论坛徽章:
0
4 [报告]
发表于 2019-01-30 15:42 |只看该作者
回复 2# cfwyy
多谢指点,两种方法都是可行的。我试了一下把for循环写到cmd里也可以实现,从getline得到的是一行记录,还要再split分割一下。代码如下:
  1. awk 'END{"for i in {7..1}; do printf $(date --date \"$i day ago \" +%Y-%m-%d),; done " |getline tmp; split(tmp,date,","); for (i=1;i<length(date);i++)  print date[i] }' tmp.txt
  2. 2019-01-23
  3. 2019-01-24
  4. 2019-01-25
  5. 2019-01-26
  6. 2019-01-27
  7. 2019-01-28
  8. 2019-01-29
复制代码
这种方法可以避免在shell中调用awk变量i。从实用角度来说,我觉得还是你给出的方法更好一些。

论坛徽章:
8
2016科比退役纪念章
日期:2018-10-24 08:24:0115-16赛季CBA联赛之北控
日期:2019-03-12 14:34:562016科比退役纪念章
日期:2019-04-01 10:33:0915-16赛季CBA联赛之山东
日期:2019-04-17 12:46:3215-16赛季CBA联赛之广夏
日期:2019-05-09 16:40:4015-16赛季CBA联赛之广夏
日期:2019-10-10 15:33:4015-16赛季CBA联赛之辽宁
日期:2019-10-15 08:37:0615-16赛季CBA联赛之北控
日期:2021-03-30 15:53:34
5 [报告]
发表于 2019-01-30 17:00 |只看该作者
回复 4# zhxinling

哦,对 ,就相当于循环用shell的for完成了。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP