打印文件的前N个单词

6
有没有办法打印文件的前N个单词?我尝试使用cut命令,但它是逐行读取文档的。我想到的唯一解决方法是:
sed ':a;N;$!ba;s/\n/δ/g' file | cut -d " " -f -20 | sed 's/δ/\n/g'

基本上,将换行符替换为文件中不存在的字符,使用空格作为分隔符应用“cut”,然后恢复换行符。
是否有更好的解决方案?

定义一个“单词”,并提供一些样例输入和预期输出。 - Ed Morton
5个回答

4
您可以使用 awk 命令打印前 n 个单词:
$ awk 'NR<=8{print;next}{exit}' RS='[[:blank:]]+|\n' file

这将打印出前8个单词。每个单词都会在单独的一行输出,您是否希望保留文件的原始格式?
编辑:
以下内容将保留文件的原始格式:
awk -v n=8 'n==c{exit}n-c>=NF{print;c+=NF;next}{for(i=1;i<=n-c;i++)printf "%s ",$i;print x;exit}' file

演示:

$ cat file
one two
thre four five six
seven 8 9 
10

$ awk -v n=8 'n==c{exit}n-c>=NF{print;c+=NF;next}{for(i=1;i<=n-c;i++)printf "%s ",$i;print x;exit}' file
one two
thre four five six
seven 8 

一个小注意点:如果最后一行打印的不是一个空格作为分隔符,那么这行文字将失去其格式。
$ cat file 
one     two
thre     four five six
seven        8 9 
10

# the 8th word fell on 3rd line: this line will be formatted with single spaces
$ awk -v n=8 'n==c{exit}n-c>=NF{print;c+=NF;next}{for(i=1;i<=n-c;i++)printf "%s ",$i;print x;exit}' file
one     two
thre     four five six
seven 8

3
假设单词由空格分隔,您可以使用 tr 将文档转换为每行一个单词的格式,然后计算前N行:
tr -s ' \011' '\012' < file | head -n $N

N=20 替换为您想要的单词数。请注意,tr 是一个纯过滤器;它只从标准输入读取,并且只写入标准输出。选项-s 压缩重复替换,所以您会在输入的每个空格或制表符序列中得到一个换行符。(如果文件中有前导空格,则您将获得一个初始空行。有各种方法可以处理这个问题,例如获取输出的前N+1行,或者过滤掉所有空行。)


还有:tr -s [[:space:]] \\n - William Pursell

1

使用GNU awk,我们可以将RS设置为正则表达式,并使用RT访问匹配的字符串:

$ cat file
the quick
brown     fox     jumped over
the
lazy
dog's back

$ gawk -v c=3 -v RS='[[:space:]]+' 'NR<=c{ORS=(NR<c?RT:"\n");print}' file
the quick
brown

$ gawk -v c=6 -v RS='[[:space:]]+' 'NR<=c{ORS=(NR<c?RT:"\n");print}' file
the quick
brown     fox     jumped over

$ gawk -v c=9 -v RS='[[:space:]]+' 'NR<=c{ORS=(NR<c?RT:"\n");print}' file
the quick
brown     fox     jumped over
the
lazy
dog's

0

一种使用 Perl 的方法:

perl -lane 'push @a,@F;END{print "@a[0..9]"}' file

注意:索引从零开始,因此示例将打印前十个单词。这些单词将在一行上打印,用一个空格分隔。

如果前N个单词中包含换行符,它们会被替换为空格吗? - Nick
@Nick 是的,目前没有回答可以保留原始文件格式。 - Chris Seymour

0

为什么不尝试将您的单词转换成行,然后只使用head -n 20呢?

例如:

for i in `cat somefile`; do echo $i; done | head -n 20

虽然不够优雅,但它确实具有较少的行噪声正则表达式。


1
那会将整个文件读入内存中,如果文件很小这并不重要,但如果文件很大就会有问题。 - Jonathan Leffler
你说得很对。它在解释bash如何将空格作为分隔符方面也相当脆弱。 - Gian
3
如果文件名包含通配符或以减号开头,则程序运行会失败,且失败方式难以理解。 - Ed Morton
同样正确。我想我只是提出了一种可能的方法,作为一种快速而粗略的方式来实现特定类型输入的结果。 - Gian
1
所有警告都已经注意到了;相对于Bash而言,它仍然是一个简单(好吧,相对而言)的方法。这里有一个版本,它不会遍历整个文件(也有一堆警告):n=0; for i in $(cat somefile); do [ ${n} -lt 20 ] && echo $i || break; ((n+=1)); done - Leo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接