打印文件的前 N 个字

Print first N words of a file

提问人:Nick 提问时间:3/25/2013 最后编辑:Chris SeymourNick 更新时间:3/26/2013 访问量:6893

问:

有什么方法可以打印文件的前 N 个单词?我试过剪切,但它一行一行地读取文档。我想出的唯一解决方案是:

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

从本质上讲,将换行符替换为文件中不存在的字符,应用带有空格的“cut”作为分隔符,然后恢复换行符。

有没有更好的解决方案?

Linux Unix 脚本 AWK

评论

0赞 Ed Morton 3/25/2013
定义一个“单词”并发布一些示例输入和预期输出。

答:

0赞 Gian 3/25/2013 #1

为什么不试着把你的话变成台词,然后用呢?head -n 20

例如:

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

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

评论

1赞 Jonathan Leffler 3/25/2013
这会将整个文件读入内存,这无关紧要,如果文件很小,但文件很大。
0赞 Gian 3/25/2013
你说得很对。关于bash选择如何将空格解释为分隔符,它也相当脆弱。
3赞 Ed Morton 3/25/2013
如果文件名包含通配符或以减号开头,它也会以神秘的方式失败,或者......
0赞 Gian 3/26/2013
也是真的。我想我只会建议一种方法,它可能是一种快速而肮脏的方法,以实现特定类型输入的结果。
1赞 Leo 10/1/2020
注意到所有警告;它对于简单明了(相对于 Bash)方法仍然有用。这是一个不遍历整个文件的版本(也有很多注意事项):n=0; for i in $(cat somefile); do [ ${n} -lt 20 ] && echo $i || break; ((n+=1)); done
3赞 Jonathan Leffler 3/25/2013 #2

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

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

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

评论

0赞 William Pursell 3/25/2013
也:。tr -s [[:space:]] \\n
4赞 Chris Seymour 3/25/2013 #3

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

$ 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
0赞 Vijay 3/25/2013 #4

perl 的一种方式:

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

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

评论

0赞 Nick 3/25/2013
如果前 N 个单词中包含换行符怎么办?它们会被空格取代吗?
0赞 Chris Seymour 3/25/2013
@Nick 是的,目前没有答案会保留原始文件格式。
1赞 Ed Morton 3/25/2013 #5

使用 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