gpt4 book ai didi

bash - 列出包含 `n` 或更少行的文件

转载 作者:行者123 更新时间:2023-11-29 08:47:36 25 4
gpt4 key购买 nike

问题

在文件夹中,我想打印包含 n=27 行或更少行的每个 .txt 文件的名称。我可以做

wc -l *.txt | awk '{if ($1 <= 27){print}}'

问题是文件夹中的许多文件有数百万行(而且行很长),因此命令 wc -l *.txt 非常慢。原则上,一个进程可以计算行数,直到找到至少 n 行,然后继续处理下一个文件。

什么是更快的替代方案?

仅供引用,我在 MAC OSX 10.11.6

尝试

这是对 awk 的尝试

#!/bin/awk -f

function printPreviousFileIfNeeded(previousNbLines, previousFILENAME)
{
if (previousNbLines <= n)
{
print previousNbLines": "previousFILENAME
}
}

BEGIN{
previousNbLines=n+1
previousFILENAME=NA
}


{
if (FNR==1)
{
printPreviousFileIfNeeded(previousNbLines, previousFILENAME)
previousFILENAME=FILENAME
}
previousNbLines=FNR
if (FNR > n)
{
nextfile
}
}

END{
printPreviousFileIfNeeded(previousNbLines, previousFILENAME)
}

可以称为

awk -v n=27 -f myAwk.awk *.txt

但是,代码无法打印出完全空的文件。我不确定如何解决这个问题,也不确定我的 awk 脚本是否适合。

最佳答案

使用 GNU awk 获取 nextfile 和 ENDFILE:

awk -v n=27 'FNR>n{f=1; nextfile} ENDFILE{if (!f) print FILENAME; f=0}' *.txt

使用任何 awk:

awk -v n=27 '
{ fnrs[FILENAME] = FNR }
END {
for (i=1; i<ARGC; i++) {
filename = ARGV[i]
if ( fnrs[filename] < n ) {
print filename
}
}
}
' *.txt

无论输入文件是否为空,它们都可以工作。非 gawk 版本的注意事项与您当前的其他 awk 答案相同:

  1. 它依赖于相同的文件名不会出现多次(例如 awk 'script' foo bar foo)并且您希望它显示多次,并且
  2. 它依赖于在 arg 列表中没有设置变量(例如 awk 'script' foo FS=, bar)

gawk 版本没有这样的限制。

更新:

测试上述 GNU awk 脚本和 the GNU grep+sed script posted by xhienne 之间的时序因为她说她的解决方案比纯 awk 脚本快我创建了 10,000 个输入文件,所有的长度都在 0 到 1000 行之间,使用这个脚本:

$ awk -v numFiles=10000 -v maxLines=1000 'BEGIN{for (i=1;i<=numFiles;i++) {numLines=int(rand()*(maxLines+1)); out="out_"i".txt"; printf "" > out; for (j=1;j<=numLines; j++) print ("foo" j) > out} }'

然后对它们运行 2 个命令并获得这些第 3 次运行计时结果:

$ time grep -c -m28 -H ^ *.txt | sed '/:28$/ d; s/:[^:]*$//' > out.grepsed

real 0m1.326s
user 0m0.249s
sys 0m0.654s

$ time awk -v n=27 'FNR>n{f=1; nextfile} ENDFILE{if (!f) print FILENAME; f=0}' *.txt > out.awk

real 0m1.092s
user 0m0.343s
sys 0m0.748s

两个脚本都产生相同的输出文件。以上是在 cygwin 上以 bash 运行的。我预计在不同的系统上,计时结果可能会略有不同,但差异总是可以忽略不计。


要打印 10 行,每行最多 20 个随机字符(请参阅注释):

$ maxChars=20
LC_ALL=C tr -dc '[:print:]' </dev/urandom |
fold -w "$maxChars" |
awk -v maxChars="$maxChars" -v numLines=10 '
{ print substr($0,1,rand()*(maxChars+1)) }
NR==numLines { exit }
'
0J)-8MzO2V\XA/o'qJH
@r5|g<WOP780
^O@bM\
vP{l^pgKUFH9
-6r&]/-6dl}pp W
&.UnTYLoi['2CEtB
Y~wrM3>4{
^F1mc9
?~NHh}a-EEV=O1!y
of

要在 awk 中完成所有操作(这会慢很多):

$ cat tst.awk
BEGIN {
for (i=32; i<127; i++) {
chars[++charsSize] = sprintf("%c",i)
}
minChars = 1
maxChars = 20
srand()
for (lineNr=1; lineNr<=10; lineNr++) {
numChars = int(minChars + rand() * (maxChars - minChars + 1))
str = ""
for (charNr=1; charNr<=numChars; charNr++) {
charsIdx = int(1 + rand() * charsSize)
str = str chars[charsIdx]
}
print str
}
}

$ awk -f tst.awk
Heer H{QQ?qHDv|
Psuq
Ey`-:O2v7[]|N^EJ0
j#@/y>CJ3:=3*b-joG:
?
^|O.[tYlmDo
TjLw
`2Rs=
!('IC
hui

关于bash - 列出包含 `n` 或更少行的文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52632590/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com