打印文件的前N个单词

有没有办法打印文件的前N个单词? 我已经尝试过,但它逐行读取文档。 我想出的唯一解决scheme是:

sed ':a;N;$!ba;s/\n/δ/g' file | cut -d " " -f -20 | sed 's/δ/\n/g' 

基本上,用文件中不存在的字符replace换行符,用空格作为分隔符应用“cut”,然后恢复换行符。

有没有更好的解决scheme?

假设单词是由空格分隔的非空格,可以使用tr将文档转换为每行一格的格式,然后计算前N行:

 tr -s ' \011' '\012' < file | head -n $N 

其中N=20或任何你想要的字数值。 请注意, tr是一个纯粹的过滤器; 它只从标准输入读取,只写入标准输出。 -s选项'挤出'重复的替换,所以你得到一个空白或标签在输入序列一个新行。 (如果文件中有空白,就会得到一个空白行,有很多种方法可以处理,比如抓取第一行N + 1行输出,或者过滤掉所有空行。

您可以使用awk打印前n个单词:

 $ awk 'NR<=8{print;next}{exit}' RS='[[:blank:]]+|\n' file 

这将打印前8个单词。 每个单词输出在一个单独的行,你是否希望保持文件的原始格式?

编辑:

以下内容将保留文件的原始格式:

 awk -vn=8 'n==c{exit}nc>=NF{print;c+=NF;next}{for(i=1;i<=nc;i++)printf "%s ",$i;print x;exit}' file 

演示:

 $ cat file one two thre four five six seven 8 9 10 $ awk -vn=8 'n==c{exit}nc>=NF{print;c+=NF;next}{for(i=1;i<=nc;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 -vn=8 'n==c{exit}nc>=NF{print;c+=NF;next}{for(i=1;i<=nc;i++)printf "%s ",$i;print x;exit}' file one two thre four five six seven 8 

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

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

一种方式与Perl:

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

注意:索引编制从零开始,因此示例将打印前十个单词。 单词将被打印在由单个空格分隔的单行上。

为什么不尝试把你的话转换成行,然后用head -n 20代替?

例如:

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

这不是优雅的,但它确实有相当少的线噪声正则表达式。