打印文件的前N个单词

时间:2013-03-25 10:08:25

标签: linux unix scripting awk

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

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

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

有没有更好的解决方案?

5 个答案:

答案 0 :(得分:2)

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

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

其中N=20或您想要的任何值的单词数量。请注意tr是一个纯粹的过滤器;它只从标准输入读取,只写入标准输出。 -s选项'挤出'重复的替换,因此您在输入中的每个空白或制表符序列中获得一个换行符。 (如果文件中有前导空格,则会得到一个初始空白行。有多种方法可以解决这个问题,例如抓住第一个N + 1行输出,或者过滤掉所有空行。)< / p>

答案 1 :(得分:2)

您可以使用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

答案 2 :(得分:1)

使用GNU awk,我们可以将RS设置为regexp并使用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

答案 3 :(得分:0)

perl的一种方式:

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

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

答案 4 :(得分:-1)

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

例如:

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

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