庆典 - 基于价值选择列
我是新来bash和有以下要求:庆典 - 基于价值选择列
我有如下文件:
col1,col2,col3....col25
s1,s2,s2..........s1
col1,col2,col3....col25
s3,s2,s2..........s2
如果你注意到这些列的值可以是3种类型只有:S1,S2,S3
我可以提取给定的文件,给了我最后2rows:
col1,col2,col3....col25
s3,s1,s2..........s2
我想进一步解析上面的行,以便我只获得具有say值的列s1。
所需的输出: 说COL3,col25与s2值的唯一列,然后说逗号分隔值也蛮好例如:
col3,col25
是否有人可以帮忙吗?
P.S.我发现很多基于say 2nd(固定)列的值解析文件的例子,但是当列号不固定时,我们该怎么做? 经过网址: awk one liner select only rows based on value of a column
假设:
- 有2条输入线
- 每个输入行具有相同数量的用逗号分隔的
我们还可以使用两个阵列收集的输入数据,确保使用相同的数组索引。一旦数据被加载到数组中,我们循环遍历数组寻找我们的值匹配。
$ cat col.awk
/col1/ { for (i=1; i<=NF; i++) { arr_c[i]=$i } ; n=NF }
! /col1/ { for (i=1; i<=NF; i++) { arr_s[i]=$i } }
END {
sep=""
for (i=1; i<=n; i++)
{ if (arr_s[i]==smatch)
{ printf "%s%s" ,sep,arr_c[i]
sep=", "
}
}
}
-
/col1/
:对包含col1
,存储在阵列中的字段arr_c
-
n=NF
行:抓住我们最大数组索引值(NF =字段数) -
! /col1/
:对于行不包含col1
,存储数组中的字段arr_s
-
END ...
:一旦数组加载就执行 -
sep=""
:设置我们的初始输出分离器为空字符串 -
for (...)
:通过我们的数组索引环路(1到n) -
if (arr_s[i]==smatch)
:如果S数组值我们的输入参数匹配(SMATCH - 见下例) ,然后... -
printf "%s%s",sep,arr_c[i]
:printf的我们sep
和对应的C数组的项目,然后... -
sep=", "
:设置我们分隔在循环
我们使用printf
,因为没有指定'\ n'(一个新行),所有输出都转到一行。
实施例:
$ cat col.out
col1,col2,col3,col4,col5
s3,s1,s2,s1,s3
$ awk -F, -f col.awk smatch=s1 col.out
col2, col4
-
-F,
:定义输入字段分隔符为逗号 - 这里我们在我们的搜索图案
s1
通过在名为smatch
数组变量,其在awk
代码中引用(请参见上面的列表)
如果你想在comman上做所有的事情d线:
$ awk -F, '
/col1/ { for (i=1; i<=NF; i++) { arr_c[i]=$i } ; n=NF }
! /col1/ { for (i=1; i<=NF; i++) { arr_s[i]=$i } }
END {
sep=""
for (i=1; i<=n; i++)
{ if (arr_s[i]==smatch)
{ printf "%s%s" ,sep,arr_c[i]
sep=", "
}
}
}
' smatch=s1 col.out
col2, col4
或折叠的END
块一行:
awk -F, '
/col1/ { for (i=1; i<=NF; i++) { arr_c[i]=$i } ; n=NF }
! /col1/ { for (i=1; i<=NF; i++) { arr_s[i]=$i } }
END { sep="" ; for (i=1; i<=n; i++) { if (arr_s[i]==smatch) { printf "%s%s" ,sep,arr_c[i] ; sep=", " } } }
' smatch=s1 col.out
col2, col4
令人惊叹的答案。它不仅工作,详细的解释是非常有用的。真是一个非凡的答案。非常感谢。 – learner
我不是awk
那么好,但这里的东西,似乎工作,仅输出列名,其对应的值是s1
:
#<yourTwoLines> |
tac |
awk -F ',' 'NR == 1 { for (f=1; f<=NF; f++) { relevant[f]= ($f == "s1") } };
NR == 2 { for (f=1; f<=NF; f++) { if(relevant[f]) print($f) } }'
它工作在方式如下:
扭转线订购带有
tac
,因此值(标准)的报头之前被处理(瓦特我们将根据标准打印)。处理以阵列与
awk
处理第二行(现在的标题)时哪些是s1
与
awk
的第一行(现在值),存储时,打印那些谁对应于s1
值感谢以前填充的数组。
谢谢,会进一步检查这个答案。 – learner
比方说,你有这样的:
cat file
col1,col2,col3,..,col25
s3,s1,s2,........,s2
然后你就可以使用这个awk
:
awk -F, -v val='s2' '{
s="";
for (i=1; i<=NF; i++)
if (NR==1)
hdr[i]=$i
else if ($i==val)
s=s hdr[i] FS;
if (s) {
sub(/,$/, "", s);
print s
}
}' file
col3,col25
感谢您的回复。 – learner
解决方案awk在分析每行2行后打印结果行。
$ cat tst.awk
BEGIN {FS=","; p=0}
/s1|s2|s3/ {
for (i=1; i<NF; i++) {
if ($i=="s2") str = sprintf("%s%s", str?str ", ":str, c[i])
};
p=1
}
!p { for (i=1; i<NF; i++) { c[i] = $i } }
p { print str; p=0; str="" }
基本原理:建立结果字符串str
当您循环访问值行时。
- 每当输入包含S1,S2或S3,循环通过的元件和 - 如果
value == s2
- , - 具有索引i
到resultstringstr
添加柱;设置打印VARp
为1 - 如果
p = 0
积聚列阵列 - 如果
p = 1
打印resultstringstr
随着输入:
$ cat input.txt
col1,col2,col3,col4,col5
s1,s2,s2,s3,s1
col1,col2,col3,col4,col5
s1,s1,s2,s3,s3
col1,col2,col3,col4,col5
s1,s1,s1,s3,s3
col1,col2,col3,col4,col5
s1,s1,s2,s3,s3
结果是:
$ awk -f tst.awk input.txt
col2, col3
col3
col3
注意空第三行:没有s2的那个。
感谢您的回复。 – learner
如果返回的列的顺序是不是一个问题
awk -F"," 'NR==1{for(i=1;i<=NF;i++){a[i]=$i};next}{for(i=1;i<=NF;i++){if($i=="s2")b[i]=$i}}END{for(i in b) m=m a[i]","; gsub(/,$/,"", m); print m }'
显示应该如何看最后的结果 – RomanPerekhrest
说COL2,COL4与值S1的唯一列,然后说一个逗号分隔值也未尝前:col2,col4 – learner
@learner,用你想要的结果集更新你的问题;在这种情况下,您可能想要更新您的示例数据,因为没有任何内容(此刻)显示col4的内容(当然,我们可以想象样本数据的样子,但在您的问题中显示它不会有什么伤害) – markp