我们说我有一个包含以下内容的数据文件:
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
如果代码并不需要我知道列和/或行的确切数量,那就太棒了。
答案 0 :(得分:2)
这将做你想要的。它不需要知道有多少行或列存在。
$ 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]
对于任何列为{0}的列i
设置为1。
由于条件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
非{0}的每列a[i]
。我选择了制表符分隔输出,但只需调整printf
语句,就可以使用任何格式。
答案 1 :(得分:1)
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:]]*\)/\2>\1/g
# remove treated column
s/>[[:blank:]]*[0-9]\{1,\}\([[:blank:]]\{1,\}[[:graph:][:blank:]]*\)/>\1/g
# is there another colum to treat ?
/>[[:blank:]]*[0-9][[:graph:][:blank:]]/ b cycle
# print result after cleanup
s/>//gp
}' YourFile
--posix
关于GNU sed 答案 2 :(得分:0)
这是使用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 $1
}
像这样运行它,例如:
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