[英]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.