免费注册 查看新帖 |

ChinaUnix.net

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1259 | 回复: 4

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

论坛徽章:
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变量。正确的格式应该怎么写呢?

论坛徽章:
1
2016科比退役纪念章
日期:2018-10-24 08:24:01
发表于 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
发表于 2019-01-30 14:53 |显示全部楼层
外裤套内裤,内裤在里。“内裤”又要时不时跑到“外裤”外面来。 --------这本身就憋着劲呢。
两套东西,兼容性再好也不如一套。
shell本来就没法调试,这样一来更雪上加霜。

shell不作为,导致awk做大,店大欺客,客大欺店。

建议早学win,linux通用的, powershell, python。
============================================================================================
powershell脚本第一课:面向对象简介1
http://bbs.chinaunix.net/thread-4263988-1-1.html


ps第二课:常用对象类型
http://bbs.chinaunix.net/thread-4264061-1-1.html



ps第三课:面向对象语言有啥优缺点?
http://bbs.chinaunix.net/thread-4264062-1-1.html



ps第4课:文件目录对象介绍
http://bbs.chinaunix.net/thread-4264293-1-1.html


ps第5课:常用帮助命令
http://bbs.chinaunix.net/thread-4264294-1-1.html


ps第6课:单个字符对象,讲ps如何处理单个字符,含汉字
http://bbs.chinaunix.net/thread-4264556-1-3.html


ps第7课:powershell到底有何优势,为什么要学?
http://bbs.chinaunix.net/thread-4264776-1-1.html


ps第8课:用powershell读写文本、二进制文件。
http://bbs.chinaunix.net/thread-4266404-1-1.html



ps第9课:powershell数组(静态,动态)
http://bbs.chinaunix.net/thread-4267455-1-1.html



ps第10课:powershell中有,世界上最好的脚本编码处理技术
http://bbs.chinaunix.net/thread-4291318-1-1.html


ps第11课:尽解powershell哈希表
http://bbs.chinaunix.net/thread-4296512-1-1.html


ps第12课:如何用ps,bash编写远程脚本
http://bbs.chinaunix.net/thread-4298680-1-2.html


ps第13课:单步、断点、图形界面,ps极大提升了linux脚本生产力
http://bbs.chinaunix.net/thread-4299559-1-2.html


ps第14课:变量的作用域
http://bbs.chinaunix.net/thread-4300246-1-1.html

论坛徽章:
0
发表于 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。从实用角度来说,我觉得还是你给出的方法更好一些。

论坛徽章:
1
2016科比退役纪念章
日期:2018-10-24 08:24:01
发表于 2019-01-30 17:00 |显示全部楼层
回复 4# zhxinling

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

本版积分规则 发表回复

数据风云,十年变迁
DTCC 第十届中国数据库技术大会已启航!

2019年5月8日~5月10日,由IT168旗下ITPUB企业社区平台主办的第十届中国数据库技术大会(DTCC2019),将在北京隆重召开。大会将邀请百余位行业专家,就热点技术话题进行分享,是广大数据领域从业人士的又一次年度盛会和交流平台。与SACC2018类似,本届大会将采用“3+2”模式:3天传统技术演讲+2天深度主题培训。大会不仅提供超100场的主题演讲,还会提供连续2天的深度课程培训,深化数据领域的项目落地实践方案。
DTCC2019,一场值得期待的数据技术盛会,殷切地希望您报名参与!

活动入口>>
  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP