【问题标题】:awk clear array values after reading each line of csvawk 读取每行 csv 后清除数组值
【发布时间】:2013-01-23 02:08:19
【问题描述】:

我遇到的问题与a previous post 有关。现在我现在拥有的是:

  1. 一个 900 万行的 CSV 文件,其中包含随机排列的字段,例如:

    192.168.12.23,62,LOCAL,341993,23/10/2012
    192.168.12.25,11,MONLOCAL$MONREMOTE,33222$56,22/10/2012$18/10/2012
    192.168.12.678,14,MONLOCAL,341993,22/10/2012
    
    192.168.12.83,18, , ,
    192.168.12.21,49,LOCAL$REMOTE,19316$15253,22/10/2012$22/10/2012
    192.168.12.79,52,REMOTE,1180306134,19/10/2012
    192.168.12.41,44,MONLOCAL$MONREMOTE,1865871$383666,22/10/2012$22/10/2012
    192.168.12.29,23,MONREMOTE,151145,18/10/2012
    

    您可能已经观察到,有 2 个字段分隔符,,$

    • 字段 1 = IP 地址

    • 字段 2 = 唯一 ID

    • 字段 3 = IP 已使用的连接(例如 LOCAL、REMOTE、MONLOCAL 或 MONREMOTE)

    • 字段 4 = 也可以是 IP 已使用的连接(例如 LOCAL、REMOTE、MONLOCAL 或 MONREMOTE)或与字段 3 相关的值

    • 字段 5 = 如果字段 4 是 LOCAL 或 REMOTE 或 MONLOCAL 或 MONREMOTE,则字段 5 表示字段 3 的值,否则表示与字段 3 相关的时间戳

    • 字段 6 = 如果字段 4 是 LOCAL 或 REMOTE 或 MONLOCAL 或 MONREMOTE,则字段 6 表示字段 4 的值,否则将不存在。

    • 字段 7 = 如果字段 4 是 LOCAL 或 REMOTE 或 MONLOCAL 或 MONREMOTE,则字段 7 表示字段 3 的时间戳,否则将不存在。

    • 字段 8 = 如果字段 4 是 LOCAL 或 REMOTE 或 MONLOCAL 或 MONREMOTE,则字段 7 表示字段 4 的时间戳,否则将不存在。

  2. 我需要处理上面的文件并输出以下格式,字段始终按以下顺序(10 个字段):

    IP,ID,MONLOCAL_value,MONLOCAL_timestamp,LOCAL_value,LOCAL_timestamp,MONREMOTE_value,MONREMOTE_timestamp,REMOTE_value,REMOTE_timestamp 比如:

    192.168.12.23,62, , ,341993,23/10/2012, , , , 
    192.168.12.25,11,33222,22/10/2012, , , , ,56,18/10/2012
    192.168.12.678,14,341993,22/10/2012, , , , , ,  
    192.168.12.83,18, , , , , , , , 
    192.168.12.21,49, , ,19316,22/10/2012, , ,15253,22/10/2012
    192.168.12.79,52, , , , , , ,1180306134,19/10/2012
    192.168.12.41,44,1865871,22/10/2012, , ,383666,22/10/2012, , 
    192.168.12.29,23, , , , ,151145,18/10/2012, , 
    
  3. 我有以下脚本来处理上面的文件:

    nawk 'BEGIN {
        while (getline < "'"$data"'" > 0)
        {
        {FS = "[,,$]"; OFS=","}
        split($0,flds)
           {if ($4 ~ /LOCAL|REMOTE|MONLOCAL|MONREMOTE/) {
                if ($3 ~ /MONLOCAL/) {
                        MONREMOTE_time=flds[8];
                        MONREMOTE_value=flds[6];
                        MONLOCAL_time=flds[7];
                        MONLOCAL_value=flds[5]; }
                if ($3 ~ /MONREMOTE/) {
                        MONREMOTE_time=flds[7];
                        MONREMOTE_value=flds[5];
                        REMOTE_value=flds[6];
                        REMOTE_time=flds[8]; }
                if ($3 ~ /REMOTE/) {
                        REMOTE_value=flds[5];
                        REMOTE_time=flds[7];
                        LOCAL_value=flds[6];
                        LOCAL_time=flds[8]; }
        } else {
                if($3 ~ /MONLOCAL/) {
                        MONLOCAL_value=flds[4];
                        MONLOCAL_time=flds[5]; }
                if ($3 ~ /MONREMOTE/) {
                        MONREMOTE_value=flds[4];
                        MONREMOTE_time=flds[5]; }
                if ($3 ~ /LOCAL/) {
                        LOCAL_value=flds[4];
                        LOCAL_time=flds[5]; }
                if ($3 ~ /REMOTE/) {
                        REMOTE_value=flds[4];
                        REMOTE_time=flds[5]; }
        }
      }
      {print MONLOCAL_value",MONLOCAL_time,LOCAL_value,LOCAL_time,MONREMOTE_value,MONREMOTE_time,REMOTE_value,REMOTE_time;}
     }
    }'
    
  4. 这里的坏处是,正如您在下面看到的那样,输出与预期不符,因为我无法在读取每一行后清除数组值,或者找到一种解决方案来为每一行动态地为数组元素充电:

    4915779000211,62, , ,341993,23/10/2012, , , , ,
    4915779000212,11,33222,22/10/2012,341993,23/10/2012,56,18/10/2012, , 
    491639000591,14,341993,22/10/2012,341993,23/10/2012, , , ,  
    491779001768,18,319307448,18/10/2012,19316,22/10/2012,383666,22/10/2012,1180306134,19/10/2012
    4915779000213,49,3849259,05/10/2012,19316,22/10/2012,56,18/10/2012,15253,22/10/2012
    491779000758,52,9356828,08/10/2012,19316,22/10/2012,56,18/10/2012,1180306134,19/10/2012
    4915779000214,44,1865871,22/10/2012,19316,22/10/2012,383666,22/10/2012,1180306134,19/10/2012
    491639000221,23,319307448,18/10/2012,19316,22/10/2012,151145,18/10/2012,1180306134,19/10/2012
    

所以,如果你们知道如何使这个 awk 函数工作并给出预期的输出,我将不胜感激。

【问题讨论】:

  • 在 BEGIN 块内的循环中执行此操作的原因并不明显。为什么不使用 awk 的 std 隐含循环,例如 awk '{ if (logic) { ...} else if (more logic) { .... } else { .... } }' file &gt;outfile 另外要重置数组,您应该能够 delete flds 然后根据需要重新分配键/值。祝你好运。

标签: bash csv awk


【解决方案1】:

通过一些修改,您可以使用类似于以下内容的内容:

while read line; do 
  if [[ "$line" == *\$* ]]; then 
    echo $line | awk -F',|\$' '{print $1,$2,$5,$6,$3}' >> newfile;
  else
    echo $line | awk -F',' '{print $1,$2,$3,,$4,,$5}' >> newfile;
  fi
done < "/path/to/your/file"

【讨论】:

  • 我已经尝试过了,但我有 1100 万行要在几个小时内解析(〜 500 行/秒),处理〜 100 000 行需要 6 个小时,这不太好。我需要留在 nawk 函数中以保持高速处理。无论如何,谢谢你的建议
猜你喜欢
  • 1970-01-01
  • 2020-01-25
  • 1970-01-01
  • 2021-12-23
  • 2014-05-09
  • 1970-01-01
  • 2015-05-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多