Shell 解析和修改文件内容

Shell 解析和修改文件内容,shell,parsing,awk,Shell,Parsing,Awk,我有一个应用程序,它生成包含由逗号(,)分隔的各种数据行的文件 例如: hostname,file_name,type,status,size(b),date,owner(user),owner(group) server1,/var,dir,ACT_VER,29987,2007-12-03 15:52:43.000,root,root server2,/DATA_File.out,file,ACT_VER,299076487,2008-10-15 05:12:23.000,marcos,roo

我有一个应用程序,它生成包含由逗号(,)分隔的各种数据行的文件

例如:

hostname,file_name,type,status,size(b),date,owner(user),owner(group)
server1,/var,dir,ACT_VER,29987,2007-12-03 15:52:43.000,root,root
server2,/DATA_File.out,file,ACT_VER,299076487,2008-10-15 05:12:23.000,marcos,root
server3,/opt,dir,29987,2009-05-03 00:13:23.000,user1,group1
server4,/var/tmp/xxz.zip,file,MOD_VER,400,2007-12-03 15:52:43.000,root,root
server1,/usr,dir,34299876,2006-12-03 15:52:43.000,root,root
server3,/local/home,dir,MOD_VER,400,2009-05-03 00:13:23.000,user2,group1
预期产出:

hostname,file_name,type,status,size(b),date,owner(user),owner(group)
server1,/var,dir,ACT_VER,29987,2007-12-03 15:52:43,root,root
server2,/DATA_File.out,file,ACT_VER,299076487,2008-10-15 05:12:23,marcos,root
server3,/opt,dir,,29987,2009-05-03 00:13:23,user1,group1
server4,/var/tmp/xxz.zip,file,MOD_VER,400,2007-12-03 15:52:43,root,root
server1,/usr,dir,,34299876,2006-12-03 15:52:43,root,root
server3,/local/home,dir,MOD_VER,400,2009-05-03 00:13:23,user2,group1
第一次查询:有时文件会遗漏第四列
状态
中的信息,这些信息可以是
动作版本
修改版本
切换版本
对置屏幕版本
。我想在缺少
状态的文件中添加一个额外的逗号(,)

第二个查询:
date
列中的数据位于'YYYY-MM-DD HH:MM:SS.MsMs(Ms=毫秒)中。我想忽略毫秒

我在awk中寻找一些东西(其他任何东西)来同时做这两件事,这在处理方面是很轻的,因为代码必须解析数百万行

对于第一个查询,我尝试了这个(很少有其他选择),但没有成功

cat file | awk -F, 'BEGIN {OFS=","}{if ($4 !~ /VER/) $4=",$4";}{print $0}'
我还没有开始处理第二个问题

我还想知道,当
*VER*
丢失时,是否应该将整个文件放入数组中,并处理第4个元素以包含额外的逗号(,),然后删除第6个元素中的
.000

不确定哪一个是流程密集度最低的

我正在RHEL6.7操作系统上使用shell脚本,测试正常 GNU Awk 3.1.7

awk -F, 'BEGIN {OFS=","}{if ($4 !~ /VER/) $4=","$4;}{print $0}' temp|awk -F, 'BEGIN {OFS=","}{$6=substr($6,0,19)}{print}'
server1,/var,dir,ACT_VER,29987,2007-12-03 15:52:43,root,root
server2,/DATA_File.out,file,ACT_VER,299076487,2008-10-15 05:12:23,marcos,root
server3,/opt,dir,,29987,2009-05-03 00:13:23,user1,group1
server4,/var/tmp/xxz.zip,file,MOD_VER,400,2007-12-03 15:52:43,root,root
server1,/usr,dir,,34299876,2006-12-03 15:52:43,root,root
server3,/local/home,dir,MOD_VER,400,2009-05-03 00:13:23,user2,group1
我考的不错 GNU Awk 3.1.7

awk -F, 'BEGIN {OFS=","}{if ($4 !~ /VER/) $4=","$4;}{print $0}' temp|awk -F, 'BEGIN {OFS=","}{$6=substr($6,0,19)}{print}'
server1,/var,dir,ACT_VER,29987,2007-12-03 15:52:43,root,root
server2,/DATA_File.out,file,ACT_VER,299076487,2008-10-15 05:12:23,marcos,root
server3,/opt,dir,,29987,2009-05-03 00:13:23,user1,group1
server4,/var/tmp/xxz.zip,file,MOD_VER,400,2007-12-03 15:52:43,root,root
server1,/usr,dir,,34299876,2006-12-03 15:52:43,root,root
server3,/local/home,dir,MOD_VER,400,2009-05-03 00:13:23,user2,group1
分两步进行

  • 对于不包含
    $4
    作为
    版本的行,请在实际
    $4
    之前插入
    。由于这里的
    是输入和输出字段分隔符,因此不能直接使用
    FS
  • 对于日期列上的所有行,即在
    $6
    上,使用
    上的
    split()

    awk 'function splitdate(var) {
             n=split(var,a,".")
             return a[1] 
         } 
         BEGIN{ FS=OFS="," } 
         NR>1 && $4 !~ /VER/{ $4=","$4; $5=splitdate($5); print; next }
         { $6=splitdate($6) }1' file
    
  • 分两步进行

  • 对于不包含
    $4
    作为
    版本的行,请在实际
    $4
    之前插入
    。由于这里的
    是输入和输出字段分隔符,因此不能直接使用
    FS
  • 对于日期列上的所有行,即在
    $6
    上,使用
    上的
    split()

    awk 'function splitdate(var) {
             n=split(var,a,".")
             return a[1] 
         } 
         BEGIN{ FS=OFS="," } 
         NR>1 && $4 !~ /VER/{ $4=","$4; $5=splitdate($5); print; next }
         { $6=splitdate($6) }1' file
    

  • 您可以使用此
    awk

    awk 'BEGIN{FS=OFS=","} NR>1 && NF<8 && $4 !~ /VER$/{$4 = OFS $4}
         {sub(/\.[0-9]{3},/, ",")} 1' file
    

    您可以使用此
    awk

    awk 'BEGIN{FS=OFS=","} NR>1 && NF<8 && $4 !~ /VER$/{$4 = OFS $4}
         {sub(/\.[0-9]{3},/, ",")} 1' file
    


    显示所显示输入的预期输出。@anubhava谢谢,我完全忘记了。我已编辑我的查询。上次编辑有一些错误。我已经纠正了。@Marcos:您的输出仍然不正确
    server4
    中仍然有
    000
    date@Inian更新。显示所显示输入的预期输出。@anubhava谢谢,我完全忘记了。我已编辑我的查询。上次编辑有一些错误。我已经纠正了。@Marcos:您的输出仍然不正确
    server4
    中仍然有
    000
    date@Inian更新。我已经测试了它,它不起作用,因此尝试了“$4”和$4。使用我的CMD进行测试第一个awk语句起作用了…我之前写的有点错误。另外,第二个awk语句有一个
    temp
    ,不确定是否需要。我运行了两个awk语句,没有
    temp
    ,但它都工作了。我已经测试过了,但没有工作,因此尝试了“$4”和$4。用我的CMD进行测试第一个awk语句工作了……我之前写的有点错误。另外,第二个awk语句有一个
    temp
    ,不确定是否需要。我运行了两个awk语句,没有
    temp
    ,它运行正常。这使得第一个
    server3
    和第二个
    server1
    的行具有
    000
    哦,是的,没错<代码>$6
    也可以是
    $5
    。编辑时假设只有具有毫秒值的字段@anubhava它不会更新第4列的第1行。另外,awk语句的第二部分不起作用,它没有替换
    .000
    。在我显示的输出中没有
    .000
    。第一行的第四列已经有
    ACT\u VER
    ,因此不需要更新。这使得第一行的
    server3
    和第二行的
    server1
    都有
    000
    哦,是的,没错<代码>$6
    也可以是
    $5
    。编辑时假设只有具有毫秒值的字段@anubhava它不会更新第4列的第1行。另外,awk语句的第二部分不起作用,它没有替换
    .000
    。在我显示的输出中没有
    .000
    。第1行的第4列已经有
    ACT\u VER
    ,因此不需要更新。