linux - 使用 Awk 根据 csv 文件中的分隔符将一列拆分为两列?

标签 linux shell awk sed

我是 shell 脚本的新手。我有一个包含 15000 行和 15 列的 csv 文件“a.csv”。它有一列名为“id_data”

它始终是 a.csv 文件中的第 3 列。

此数据集中的值如下所示:

A,B,id_data,C,D,E,F,...
a,b,12345_85485,c,d,e,f,...
a,b,45786_456322,c,d,e,f,...
a,b,12345_325489,c,d,e,f,...
a,b,_45230_14693,c,d,e,f....

其中 a-f 列的数据范围从数字到日期、字符串、链接。

我想计算第 3 列中 '_' 符号后的唯一值。

为此,我想根据 _ 之前的数字和 _ 之后的数字将此列拆分为两个不同的列,即“ID1 数据”和“ID2 数据”。拆分不是强制性的。主要目的是计算第 3 列中 '_' 之后的唯一数字。

csv 文件中的输出应如下所示:

A,B,ID1 Data,ID2 Data,D,E,F...
a,b,12345,85485,d,e,f,...
a,b,45786,456322,d,e,f,...
a,b,12345,325489,d,e,f,...
a,b,45230,4693,d,e,f,...

我已经尝试使用以下命令来完成它:

cat a.csv | sed -Ee 's/(.*)id_data/\1ID1 Data ID2 Data/' -e 's/,[_ ]/,/' -e 's/_/,/'

它按要求打印了输出。但是 csv 文件的列没有变化。打印的 o/p 看起来像 a,b,12345,85485,c,d,e,f,...

如何将更改应用于 csv 文件中的列?任何意见将是有益的。谢谢

*请注意,开头可能有空格甚至'_'。

最佳答案

能否请您尝试以下操作,这是一个通用解决方案,我们不需要在解决方案中对字段值进行硬编码,它将查找字符串 id_data第一行中的获取其列号并相应地对 Input_file 的其余行执行操作。

awk 'FNR==1{for(j=1;j<=NF;j++){if($j=="id_data"){field=j;$j="ID1_data ID2_data"}};print;next} {sub(/^_/,"",$field); sub(/_/,OFS,$field)} 1' Input_file

添加非单线性形式的解决方案:

awk '
FNR==1{
  for(j=1;j<=NF;j++){
    if($j=="id_data"){
      field=j
      $j="ID1_data  ID2_data"
    }    
  }
  print
  next
}
{
  sub(/^_/,"",$field)
  sub(/_/,OFS,$field)
}
1
'  Input_file

注意:请添加 BEGIN{FS=OFS=","}在上面的代码中,如果您的 Input_file 以逗号分隔。

解释:

awk '                                ##Starting awk program here.
FNR==1{                              ##Checking condition if FNR==1 which will be TRUE for 1st line.
  for(j=1;j<=NF;j++){                ##Started a for loop from j=1 to till value of NF here.
    if($j=="id_data"){               ##Checking condition if current field is equal to id_data then do following.
      field=j                        ##Setting field variable value to variable j value.
      $j="ID1_data  ID2_data"        ##Setting current field value to string ID1_data space ID2_data here.
    }
  }
  print                              ##Printing current line.
  next                               ##next will skip all further statements from here.
}
{
  sub(/^_/,"",$field)                ##Using substitute function to substitute starting _ with NULL in $field, where field is a variable set in first line.
  sub(/_/,OFS,$field)                ##Using substitute function to substitute  _ with OFS for $field field.
}
1                                    ##Mentioning 1 will print edited/non-edited lines.
'  Input_file                        ##Mentioning Input_file name here.


编辑: 根据 OP 的评论:

awk '
BEGIN{
  FS=OFS=","
}
FNR==1{
  for(j=1;j<=NF;j++){
    if($j=="id_data"){
      field=j
      $j="ID1_data  ID2_data"
    }    
  }
  print
  next
}
{
  sub(/^_/,"",$field)
  sub(/.*_/,OFS,$field)
}
1
'  Input_file

关于linux - 使用 Awk 根据 csv 文件中的分隔符将一列拆分为两列?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58128032/

相关文章:

c - 将 CSV 数据绘制成图表

服务器启动时出现 Java Runtime Environment SIGSEGV 错误

c - Linux 中的 getch() 和 getche() 等价于什么?

linux - 在 shell 脚本中对文件名的特定部分进行排序

linux - 将一列拆分为多行

linux - OpenLiteSpeed 性能不佳和 SSL 握手失败 (5)

python - 从 Django shell 上传图像

Linux 文件获取列与特定日期时间范围匹配的行

linux - awk 将字段数据复制到新字段

awk - 删除找到的每一行