如何打印包含值的列
How to print columns containing value
假设我有一个包含以下内容的数据文件:
1 2 3 4 5
67 88 12 32 22
9 99 34 59 86
17 0 78 0 77
11 0 0 0 43
我想要一个代码在每一列中搜索数字 0。如果找到数字 0,该代码将在一个单独的文件中打印出整列。
使用这些数据,输出的文件将如下所示:
2 3 4
88 12 32
99 34 59
0 78 0
0 0 0
如果代码不需要我知道 and/or 行的确切列数,那就太好了。
这会做你想做的。它不需要知道有多少行或列。
$ awk 'FNR==NR{for (i=1;i<=NF;i++)if ($i==o)a[i]=1;next} {tab="";for (i=1;i<=NF;i++)if (a[i]){printf "%s%s",tab,$i; tab="\t"};print ""}' file file
2 3 4
88 12 32
99 34 59
0 78 0
0 0 0
工作原理
因为文件名在命令行中指定了两次,所以awk
脚本将读取文件两次,第一次查找零,第二次打印。
FNR==NR{for (i=1;i<=NF;i++)if ($i==o)a[i]=1;next}
通过文件的第一个 运行,a[i]
被设置为任何包含零的列 i
。
由于条件 FNR==NR
,此代码仅适用于第一个 运行。 NR
是我们到目前为止已经读取的记录总数(行)。 FNR
是我们到目前为止从当前文件中读取的记录(行)数。因此,当FNR==NR
时,我们仍在读取第一个文件。命令末尾的 next
告诉 awk
跳过剩余的命令并从下一行开始。
tab="";for (i=1;i<=NF;i++)if (a[i]){printf "%s%s",tab,$i; tab="\t"};print ""
当我们第二次读取文件时,我们打印出 i
的每一列 a[i]
是非零的。我选择了制表符分隔的输出,但是通过简单地调整 printf
语句,可以使用任何格式。
sed '#n
# init and load line in buffer (1st line copied, other added)
s/.*/>& /;1!H;1h
# at end of file, load buffer in working area
$ {x
:cycle
# keep column if zero inside
/>[[:blank:]]*0[[:blank:]]/ s/>\(\([[:blank:]]*[0-9]\{1,\}\)[[:blank:]][[:graph:][:blank:]]*\)/>/g
# remove treated column
s/>[[:blank:]]*[0-9]\{1,\}\([[:blank:]]\{1,\}[[:graph:][:blank:]]*\)/>/g
# is there another colum to treat ?
/>[[:blank:]]*[0-9][[:graph:][:blank:]]/ b cycle
# print result after cleanup
s/>//gp
}' YourFile
的自我评论
- posix 版本为
--posix
在 GNU 上为
这里有一个使用 GNU awk 的有趣方法:
parse.awk
# Record number of columns (assuming all columns have the same number of fields)
NR == 1 { n = NF }
# First parse: Remember which columns contain `pat`
FNR == NR {
for(i=1; i<=NF; i++)
if($i == pat) {
h[i] = i
last = i>last ? i : last
}
next
}
# Before second parse: switch to reading one field at a time
ENDFILE {
RS="[ \t\n]+"
}
# Second parse: print field if current-record-number modulo
# number-of-columns is in the `h` hash
{ m = FNR % n }
m in h {
ORS = (m == last) ? "\n" : OFS # print new-line after last column
print
}
运行 例如:
awk -f parse.awk pat=0 infile infile
输出:
2 3 4
88 12 32
99 34 59
0 78 0
0 0 0
或 OFS='\t'
:
awk -f parse.awk pat=0 OFS='\t' infile infile
输出:
2 3 4
88 12 32
99 34 59
0 78 0
0 0 0
假设我有一个包含以下内容的数据文件:
1 2 3 4 5
67 88 12 32 22
9 99 34 59 86
17 0 78 0 77
11 0 0 0 43
我想要一个代码在每一列中搜索数字 0。如果找到数字 0,该代码将在一个单独的文件中打印出整列。
使用这些数据,输出的文件将如下所示:
2 3 4
88 12 32
99 34 59
0 78 0
0 0 0
如果代码不需要我知道 and/or 行的确切列数,那就太好了。
这会做你想做的。它不需要知道有多少行或列。
$ awk 'FNR==NR{for (i=1;i<=NF;i++)if ($i==o)a[i]=1;next} {tab="";for (i=1;i<=NF;i++)if (a[i]){printf "%s%s",tab,$i; tab="\t"};print ""}' file file
2 3 4
88 12 32
99 34 59
0 78 0
0 0 0
工作原理
因为文件名在命令行中指定了两次,所以awk
脚本将读取文件两次,第一次查找零,第二次打印。
FNR==NR{for (i=1;i<=NF;i++)if ($i==o)a[i]=1;next}
通过文件的第一个 运行,
a[i]
被设置为任何包含零的列i
。由于条件
FNR==NR
,此代码仅适用于第一个 运行。NR
是我们到目前为止已经读取的记录总数(行)。FNR
是我们到目前为止从当前文件中读取的记录(行)数。因此,当FNR==NR
时,我们仍在读取第一个文件。命令末尾的next
告诉awk
跳过剩余的命令并从下一行开始。tab="";for (i=1;i<=NF;i++)if (a[i]){printf "%s%s",tab,$i; tab="\t"};print ""
当我们第二次读取文件时,我们打印出
i
的每一列a[i]
是非零的。我选择了制表符分隔的输出,但是通过简单地调整printf
语句,可以使用任何格式。
sed '#n
# init and load line in buffer (1st line copied, other added)
s/.*/>& /;1!H;1h
# at end of file, load buffer in working area
$ {x
:cycle
# keep column if zero inside
/>[[:blank:]]*0[[:blank:]]/ s/>\(\([[:blank:]]*[0-9]\{1,\}\)[[:blank:]][[:graph:][:blank:]]*\)/>/g
# remove treated column
s/>[[:blank:]]*[0-9]\{1,\}\([[:blank:]]\{1,\}[[:graph:][:blank:]]*\)/>/g
# is there another colum to treat ?
/>[[:blank:]]*[0-9][[:graph:][:blank:]]/ b cycle
# print result after cleanup
s/>//gp
}' YourFile
-
的自我评论
- posix 版本为
--posix
在 GNU 上为
这里有一个使用 GNU awk 的有趣方法:
parse.awk
# Record number of columns (assuming all columns have the same number of fields)
NR == 1 { n = NF }
# First parse: Remember which columns contain `pat`
FNR == NR {
for(i=1; i<=NF; i++)
if($i == pat) {
h[i] = i
last = i>last ? i : last
}
next
}
# Before second parse: switch to reading one field at a time
ENDFILE {
RS="[ \t\n]+"
}
# Second parse: print field if current-record-number modulo
# number-of-columns is in the `h` hash
{ m = FNR % n }
m in h {
ORS = (m == last) ? "\n" : OFS # print new-line after last column
print
}
运行 例如:
awk -f parse.awk pat=0 infile infile
输出:
2 3 4
88 12 32
99 34 59
0 78 0
0 0 0
或 OFS='\t'
:
awk -f parse.awk pat=0 OFS='\t' infile infile
输出:
2 3 4
88 12 32
99 34 59
0 78 0
0 0 0