Unix-文件中的列数


77

给定一个包含这样数据的文件(即stores.dat文件)

sid|storeNo|latitude|longitude
2|1|-28.03720000|153.42921670
9|2|-33.85090000|151.03274200

输出列名数量的命令是什么?

例如,在上面的示例中,该值为4。(第一行中的竖线字符数+ 1)

我在想类似的东西:

awk '{ FS = "|" } ; { print NF}' stores.dat

但它返回所有行,而不仅仅是第一行,对于第一行,它返回1而不是4

Answers:


117
awk -F'|' '{print NF; exit}' stores.dat 

刚在第一行之后退出。


3
awk -F'|' 'NR==1{print NF}' stores.dat
jaypal singh

10
@JaypalSingh:它将读取整个文件-不需要这样做,最好尽早停止。

它们似乎都返回相同的正确输出,相对于其他性能收益(或其他收益)有1吗?
toop

2
@toop:是的,请参阅我之前的评论。我的版本只会从文件中读取一个块,而Jaypal的则会读取整个文件。

1
@Mat你在现场!@loop Mat是绝对正确的。exit是正确的方法。如果您只想知道列数,则无需读取整个文件。+1 :)
jaypal singh 2011年

37

这是一种解决方法(对我来说:我不经常使用awk):

显示包含数据的文件的第一行,用换行符替换所有管道,然后计算行数:

$ head -1 stores.dat | tr '|' '\n' | wc -l

9
对于具有maaany列的文件(请考虑SNP数据),这就是方法。Mat的解决方案返回“ awk:超出程序限制:最大字段数=32767。”
Unfun Cat 2013年

11

除非在那里使用空格,否则应该可以| wc -w在第一行使用。

wc是“字数统计”,它只是对输入文件中的字数进行计数。如果只发送一行,它将告诉您列数。


我尝试过:头-1 store.dat | wc -w但这并不能返回我
想要的结果

那是因为您没有用|空格代替-wc将计算必须以空格分隔的单词。使用head -1 stores.dat | tr '|' ' ' | wc -w
Tom van der Woerdt 2011年

2
为了完整起见,请将您的评论添加到答案中。
Xofo


2

Perl解决方案类似于Mat的awk解决方案:

perl -F'\|' -lane 'print $#F+1; exit' stores.dat

我已经在具有1000000列的文件上进行了测试。


如果字段分隔符是空格(一个或多个空格或制表符)而不是管道:

perl -lane 'print $#F+1; exit' stores.dat

1

如果您安装了python,则可以尝试:

python -c 'import sys;f=open(sys.argv[1]);print len(f.readline().split("|"))' \
    stores.dat

在这种情况下,从标准输入中读取内容会更短cat x.txt | python -c "print raw_input().count('|') + 1"
Lie Ryan

是的,较短的是,但是如果有很多长文件,则不要更快!我认为他希望在纯(肯定是大)数据文件的眼中更快的解决方案。
唐提问

1

这通常是我用来计算字段数的内容:

head -n 1 file.name | awk -F'|' '{print NF; exit}'

1

选择文件中的任何行(在下面的示例中,它是第二行)并计算列数,其中分隔符为空格:

sed -n 2p text_file.dat | tr ' ' '\n' | wc -l

0

基于Cat Kerr的响应。该命令在solaris上起作用

awk '{print NF; exit}' stores.dat

然后,您得到的答案是正确的字段分隔符。对于示例输入,这将返回“ 1”。
本杰明·W.

这基本上与不带字段分隔符的已接受答案相同,因为Bejamin说返回1,但应该适用于以空格分隔的文件。
discipulus's


0

适当的纯净 方式

在bash下,您可以简单地:

IFS=\| read -ra headline <stores.dat
echo ${#headline[@]}
4

不使用前叉相比,速度要快得多,并且在$headline保持完整的头线的情况下可重复使用。您可以,例如:

printf " - %s\n" "${headline[@]}"
 - sid
 - storeNo
 - latitude
 - longitude

注意该语法将正确驱动列名中的空格和其他字符。

替代方案:对每行的最大列进行强二进制检查

如果某行包含一些额外的列怎么办?

该命令将搜索更大的行,计算分隔符

tr -dc $'\n|' <stores.dat |wc -L
3

最多有3个分隔符,然后是4个字段。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.