awk:更改字段分隔符,保持第一列不变
awk: change field separator keeping first column as is
我有一个只有一列的 in.csv
文件:
Sample
a_b_c
d_e_f
g_h_i
我想将字段分隔符从 _
更改为 ,
并打印单独的字段,但将输入列保留在输出文件的第一列中。原则上想用awk
这是我目前拥有的:
awk 'BEGIN {FS="_";OFS=","} {=}1' in.csv > out.csv
这给了我这个
Sample
a,b,c
d,e,f
g,h,i
我怎样才能像这样输出它,同时保留原始列(重命名 ID
)?
ID,group1,group2,group3
a_b_c,a,b,c
d_e_f,d,e,f
g_h_i,g,h,i
请注意,输入的字段数是可变的,输入的 Sample
行可能是其他名称,或者为空,甚至 non-existent,但我仍然希望这样的输出。 ..
编辑
检查所有答案后,我必须在这里澄清上面的输入文件只是一个例子......我的真实文件通常有超过3个字段,由_
分隔(但我没有事先知道有多少)和无数行,但是我会尝试确保给定文件中的所有行在要“拆分”的字段数上是一致的。
当我的文件每行要拆分的字段多于或少于 3 个时,下面的答案似乎不起作用,如果可能的话,我需要一个更通用的 one-liner。
目前,为了简单起见,我宁愿不对 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
最理想的情况是,one-liner 应该处理存在具有不一致字段的行的情况,因此来自这样的文件:
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
有没有办法在变量中记录_
的行,然后用_
分割变量,然后打印变量及其所有组件用[=分隔20=]?抱歉,我认为这会更容易...也许使用 Perl
one-liner 会更容易?抱歉,对 one-liner 不是很熟练...再次感谢!
我看不出有什么理由改变 FS。只需打印您真正想要打印的内容,而不是使用某些默认 awk
行为 {=}1
。
awk '
BEGIN {FS="_"; OFS=","}
NR==1{print "ID,group1,group2,group3"}
NR!=1{print [=10=], , , }
'
您能否尝试仅在显示的样本上进行以下、编写和测试。这应该适用于任何数量的字段,也在 https://ideone.com/fWgggq
中对其进行了测试
awk '
BEGIN{
FS="_"
OFS=","
print "ID,group1,group2,group3"
}
FNR>1{
val=[=10=]
=
print val,[=10=]
}' 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=[=11=] ##Store current line into var val here.
= ##reassign first field to itself so that new OFS which is , is implemented to whole line.
print val,[=11=] ##Printing current new line here.
}' Input_file ##Mentioning Input_file name here.
考虑以下简短的 awk
脚本,结合上面评论者的意见。它将根据第 2 行中的数据生成 header 行 - 以匹配字段数
awk '
NR > 1 {
n=split([=10=], a, "_") ;
if (NR == 2 ) { printf "ID" ; for (i=1 ; i<=n ; i++) printf ",group%d", i ; printf "\n" }
v=[=10=]
sub("_", ",", v)
print [=10=] "," v
}' filename.txt
另一个不处理 header 行(无论如何,留作练习等):
$ awk '
BEGIN {
FS="_" # set delimiters
OFS=","
}
{
for(i=0;i<=NF;i++) # loop from 0 to get [=10=]
printf "%s%s",$i,(i==NF?ORS:OFS) # print dealing with OFS and EOL
}' file
输出:
Sample,Sample
a_b_c,a,b,c
d_e_f,d,e,f
g_h_i,g,h,i
还有一个处理 具有可变组数的不同输入文件 从第一个数据记录中选取 header 计数 (NR==2
) :
$ 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 [=12=]
printf "%s%s",$i,(i==NF?ORS:OFS) # print dealing with OFS and ORS
}' file
输出:
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 '[=14=]=[=14=] (gensub(/(^|_)/,",","g"))' file
为了好玩这里还有一个awk
:
awk 'NR==1{print "ID,group1,group2,group3"; next}
{s=[=10=]; gsub(/^|_/, ","); print s [=10=]}' file
ID,group1,group2,group3
a_b_c,a,b,c
d_e_f,d,e,f
g_h_i,g,h,i
我有一个只有一列的 in.csv
文件:
Sample
a_b_c
d_e_f
g_h_i
我想将字段分隔符从 _
更改为 ,
并打印单独的字段,但将输入列保留在输出文件的第一列中。原则上想用awk
这是我目前拥有的:
awk 'BEGIN {FS="_";OFS=","} {=}1' in.csv > out.csv
这给了我这个
Sample
a,b,c
d,e,f
g,h,i
我怎样才能像这样输出它,同时保留原始列(重命名 ID
)?
ID,group1,group2,group3
a_b_c,a,b,c
d_e_f,d,e,f
g_h_i,g,h,i
请注意,输入的字段数是可变的,输入的 Sample
行可能是其他名称,或者为空,甚至 non-existent,但我仍然希望这样的输出。 ..
编辑
检查所有答案后,我必须在这里澄清上面的输入文件只是一个例子......我的真实文件通常有超过3个字段,由_
分隔(但我没有事先知道有多少)和无数行,但是我会尝试确保给定文件中的所有行在要“拆分”的字段数上是一致的。
当我的文件每行要拆分的字段多于或少于 3 个时,下面的答案似乎不起作用,如果可能的话,我需要一个更通用的 one-liner。
目前,为了简单起见,我宁愿不对 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
最理想的情况是,one-liner 应该处理存在具有不一致字段的行的情况,因此来自这样的文件:
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
有没有办法在变量中记录_
的行,然后用_
分割变量,然后打印变量及其所有组件用[=分隔20=]?抱歉,我认为这会更容易...也许使用 Perl
one-liner 会更容易?抱歉,对 one-liner 不是很熟练...再次感谢!
我看不出有什么理由改变 FS。只需打印您真正想要打印的内容,而不是使用某些默认 awk
行为 {=}1
。
awk '
BEGIN {FS="_"; OFS=","}
NR==1{print "ID,group1,group2,group3"}
NR!=1{print [=10=], , , }
'
您能否尝试仅在显示的样本上进行以下、编写和测试。这应该适用于任何数量的字段,也在 https://ideone.com/fWgggq
中对其进行了测试awk '
BEGIN{
FS="_"
OFS=","
print "ID,group1,group2,group3"
}
FNR>1{
val=[=10=]
=
print val,[=10=]
}' 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=[=11=] ##Store current line into var val here.
= ##reassign first field to itself so that new OFS which is , is implemented to whole line.
print val,[=11=] ##Printing current new line here.
}' Input_file ##Mentioning Input_file name here.
考虑以下简短的 awk
脚本,结合上面评论者的意见。它将根据第 2 行中的数据生成 header 行 - 以匹配字段数
awk '
NR > 1 {
n=split([=10=], a, "_") ;
if (NR == 2 ) { printf "ID" ; for (i=1 ; i<=n ; i++) printf ",group%d", i ; printf "\n" }
v=[=10=]
sub("_", ",", v)
print [=10=] "," v
}' filename.txt
另一个不处理 header 行(无论如何,留作练习等):
$ awk '
BEGIN {
FS="_" # set delimiters
OFS=","
}
{
for(i=0;i<=NF;i++) # loop from 0 to get [=10=]
printf "%s%s",$i,(i==NF?ORS:OFS) # print dealing with OFS and EOL
}' file
输出:
Sample,Sample
a_b_c,a,b,c
d_e_f,d,e,f
g_h_i,g,h,i
还有一个处理 具有可变组数的不同输入文件 从第一个数据记录中选取 header 计数 (NR==2
) :
$ 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 [=12=]
printf "%s%s",$i,(i==NF?ORS:OFS) # print dealing with OFS and ORS
}' file
输出:
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 '[=14=]=[=14=] (gensub(/(^|_)/,",","g"))' file
为了好玩这里还有一个awk
:
awk 'NR==1{print "ID,group1,group2,group3"; next}
{s=[=10=]; gsub(/^|_/, ","); print s [=10=]}' file
ID,group1,group2,group3
a_b_c,a,b,c
d_e_f,d,e,f
g_h_i,g,h,i