繁体   English   中英

awk:更改字段分隔符,保持第一列不变

[英]awk: change field separator keeping first column as is

我有一个in.csv文件,其中只有一列以这种方式:

Sample
a_b_c
d_e_f
g_h_i

我想将字段分隔符从_更改为,并打印单独的字段,但将输入列保持在 output 文件的第一列中。 原则上我想使用awk

这是我到目前为止所拥有的:

awk 'BEGIN {FS="_";OFS=","} {$1=$1}1' in.csv > out.csv

这给了我这个

Sample
a,b,c
d,e,f
g,h,i

我怎么能像这样 output ,保留原始列(重命名ID )?

ID,group1,group2,group3
a_b_c,a,b,c
d_e_f,d,e,f
g_h_i,g,h,i

请注意,输入的字段数是可变的,输入Sample行可能是其他名称,或者为空,甚至不存在,但我仍然想要 output 那样...

编辑

检查完所有答案后,我必须在这里澄清一下,上面的输入文件只是一个例子......我的真实文件通常有3个以上的字段,由_分隔(但我不知道事先有多少)和无数行,但是,我将尝试确保给定文件中的所有行在要“拆分”的字段数上保持一致。

当我的文件每行拆分的字段多于或少于 3 个时,下面的答案似乎不起作用,如果可能的话,我需要一个更通用的单行。

目前,为了简单起见,我宁愿不对 header 线做任何事情并保持原样。

这意味着对于另一个示例:

Some_header
a_b_c_1
d_e_f_2
g_h_i_3

我想得到这个:

Some_header
a_b_c_1,a,b,c,1
d_e_f_2,d,e,f,2
g_h_i_3,g,h,i,3

最佳情况下,单行应该处理存在字段不一致的行的情况,因此从这样的文件中:

Some_header
a_b_c
d_e_f_2
g_h_i_3_4

我想得到这个:

Some_header
a_b_c,a,b,c
d_e_f_2,d,e,f,2
g_h_i_3_4,g,h,i,3,4

有没有办法在变量中记录带有_的行,然后用_拆分变量,然后打印由,分隔的变量及其所有组件? 抱歉,我认为这会更容易......也许使用Perl会更容易? 抱歉,对单行词不太熟练……再次感谢!

您能否尝试仅在所示样本上进行以下、编写和测试。 这应该适用于在https://ideone.com/fWgggq中测试过的任意数量的字段

awk '
BEGIN{
  FS="_"
  OFS=","
  print "ID,group1,group2,group3"
}
FNR>1{
  val=$0
  $1=$1
  print val,$0
}'  Input_file

说明:为上述添加详细说明。

awk '                                   ##Starting awk program from here.
BEGIN{                                  ##Starting BEGIN section of program from here.
  FS="_"                                ##Setting field separator as _ here,
  OFS=","                               ##Setting OFS as comma here.
  print "ID,group1,group2,group3"       ##Printing header as per OP requirement here.
}
FNR>1{                                  ##Checking condition if this is greater than 1st line then do following.
  val=$0                                ##Store current line into var val here.
  $1=$1                                 ##reassign first field to itself so that new OFS which is , is implemented to whole line.
  print val,$0                          ##Printing current new line here.
}'  Input_file                          ##Mentioning Input_file name here.

然而,另一个不处理 header 线(atm 无论如何,留作练习等):

$ awk '
BEGIN {
    FS="_"                                # set delimiters
    OFS=","
}
{
    for(i=0;i<=NF;i++)                    # loop from 0 to get $0
        printf "%s%s",$i,(i==NF?ORS:OFS)  # print dealing with OFS and EOL
}' file

Output:

Sample,Sample
a_b_c,a,b,c
d_e_f,d,e,f
g_h_i,g,h,i

另一个确实处理具有可变数量组的不同输入文件,从第一条数据记录( NR==2 )中选择 header 计数:

$ awk '
BEGIN {
    FS="_"                                # set delimiters
    OFS=","
}
NR>=2 {                                   # process only data records, not header
    if(NR==2)                             # create the header
        for(i=0;i<=NF;i++)
            printf "%s%s",(i==0?"ID":"group" i),(i==NF?ORS:OFS)
    for(i=0;i<=NF;i++)                    # loop from 0 to get $0
        printf "%s%s",$i,(i==NF?ORS:OFS)  # print dealing with OFS and ORS
}' file

Output:

ID,group1,group2,group3
a_b_c,a,b,c
d_e_f,d,e,f
g_h_i,g,h,i

最后是一个简短的使用 GNU awk:

$ awk '$0=$0 (gensub(/(^|_)/,",","g"))' file

我认为没有理由改变 FS。 只需打印您想要实际打印的内容,而不是{$1=$1}1使用一些默认awk行为。

awk '
   BEGIN {FS="_"; OFS=","}
   NR==1{print "ID,group1,group2,group3"}
   NR!=1{print $0, $1, $2, $3}
'

只是为了好玩,这里还有另一个awk

awk 'NR==1{print "ID,group1,group2,group3"; next}
{s=$0; gsub(/^|_/, ","); print s $0}' file
ID,group1,group2,group3
a_b_c,a,b,c
d_e_f,d,e,f
g_h_i,g,h,i

考虑以下简短的awk脚本,结合上述评论者的输入。 它将根据第 2 行中的数据生成 header 行 - 以匹配字段数

awk '
NR > 1 {
    n=split($0, a, "_") ;
    if (NR == 2 ) { printf "ID" ; for (i=1 ; i<=n ; i++) printf ",group%d", i ; printf "\n" }
    v=$0
    sub("_", ",", v)
    print $0 "," v
}' filename.txt

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM