Bash:使用 cut 提取列并进一步过滤一列
Bash: extract columns with cut and filter one column further
我有一个制表符分隔的文件,想用 cut
提取几列。
两个示例行
(...)
0 0 1 0 AB=1,2,3;CD=4,5,6;EF=7,8,9 0 0
1 1 0 0 AB=2,1,3;CD=1,1,2;EF=5,3,4 0 1
(...)
我想要实现的是 select 第 2、3、5 和 7 列,但是仅来自第 5 列 CD=4,5,6
。
所以我的预期结果是
0 1 CD=4,5,6; 0
1 0 CD=1,1,2; 1
如何使用 cut 来解决这个问题,并在其中一个提取的列上使用 运行 grep
?任何其他单线当然也可以。
使用 awk
更容易完成。使用 ;
作为分隔符拆分第 5 个字段,然后打印第二个子字段。
awk 'BEGIN {FS="\t"; OFS="\t"}
{split(, a, ";"); print , , a[2]";", }' inputfile > outputfile
如果要打印以 CD=
开头的子字段,请使用循环:
awk 'BEGIN {FS="\t"; OFS="\t"}
{n = split(, a, ";");
for (i = 1; i <= n; i++) {
if (a[i] ~ /^CD=/) subfield = a[i];
}
print , , subfield";", }' < inputfile > outputfile
这是另一个awk
$ awk -F'\t|;' -v OFS='\t' '{print ,,,$NF}' file
0 1 CD=4,5,6 0
1 0 CD=1,1,2 1
或与cut/paste
$ paste <(cut -f2,3 file) <(cut -d';' -f2 file) <(cut -f7 file)
0 1 CD=4,5,6 0
1 0 CD=1,1,2 1
我认为 awk
是完成此类任务的最佳工具,另外两个答案为您提供了很好的简短解决方案。
我想指出的是,您可以使用 awk's
内置的拆分工具在解析输入时获得更大的灵活性。这是一个使用隐式拆分的示例脚本:
parse.awk
# Remember second, third and seventh columns
{
a =
b =
d =
}
# Split the fifth column on ";". After this the positional variables
# (e.g. , # , ..., $NF) contain the fields from the previous
# fifth column
{
oldFS = FS
FS = ";"
[=10=] =
}
# For example to test if the second elemnt starts with "CD", do
# something like this
~ /^CD/ {
c =
}
# Print the selected elements
{
print a, b, c, d
}
# Restore FS
{
FS = oldFS
}
运行 像这样:
awk -f parse.awk FS='\t' OFS='\t' infile
输出:
0 1 CD=4,5,6 0
1 0 CD=1,1,2 1
我有一个制表符分隔的文件,想用 cut
提取几列。
两个示例行
(...)
0 0 1 0 AB=1,2,3;CD=4,5,6;EF=7,8,9 0 0
1 1 0 0 AB=2,1,3;CD=1,1,2;EF=5,3,4 0 1
(...)
我想要实现的是 select 第 2、3、5 和 7 列,但是仅来自第 5 列 CD=4,5,6
。
所以我的预期结果是
0 1 CD=4,5,6; 0
1 0 CD=1,1,2; 1
如何使用 cut 来解决这个问题,并在其中一个提取的列上使用 运行 grep
?任何其他单线当然也可以。
使用 awk
更容易完成。使用 ;
作为分隔符拆分第 5 个字段,然后打印第二个子字段。
awk 'BEGIN {FS="\t"; OFS="\t"}
{split(, a, ";"); print , , a[2]";", }' inputfile > outputfile
如果要打印以 CD=
开头的子字段,请使用循环:
awk 'BEGIN {FS="\t"; OFS="\t"}
{n = split(, a, ";");
for (i = 1; i <= n; i++) {
if (a[i] ~ /^CD=/) subfield = a[i];
}
print , , subfield";", }' < inputfile > outputfile
这是另一个awk
$ awk -F'\t|;' -v OFS='\t' '{print ,,,$NF}' file
0 1 CD=4,5,6 0
1 0 CD=1,1,2 1
或与cut/paste
$ paste <(cut -f2,3 file) <(cut -d';' -f2 file) <(cut -f7 file)
0 1 CD=4,5,6 0
1 0 CD=1,1,2 1
我认为 awk
是完成此类任务的最佳工具,另外两个答案为您提供了很好的简短解决方案。
我想指出的是,您可以使用 awk's
内置的拆分工具在解析输入时获得更大的灵活性。这是一个使用隐式拆分的示例脚本:
parse.awk
# Remember second, third and seventh columns
{
a =
b =
d =
}
# Split the fifth column on ";". After this the positional variables
# (e.g. , # , ..., $NF) contain the fields from the previous
# fifth column
{
oldFS = FS
FS = ";"
[=10=] =
}
# For example to test if the second elemnt starts with "CD", do
# something like this
~ /^CD/ {
c =
}
# Print the selected elements
{
print a, b, c, d
}
# Restore FS
{
FS = oldFS
}
运行 像这样:
awk -f parse.awk FS='\t' OFS='\t' infile
输出:
0 1 CD=4,5,6 0
1 0 CD=1,1,2 1