使用awk或sed比较多个文件的长度

时间:2015-08-18 14:58:47

标签: linux bash awk sed

我想比较每个文件的行数,并选择包含最大行数的行  例如

filename_V1 |wc -l =100
filename_V2 |wc -l =19
filename_V3  |wc -l =10

myFile_V1  |wc -l =1
myFile_V2  |wc -l =10
myFile_V3  |wc -l =15

我将得到结果

filename_V1
myFile_V3

7 个答案:

答案 0 :(得分:2)

以下是考虑按基本部分分组的文件(_Vn之前的内容)并打印每组中线数最多的文件。

编辑:只是指出awk脚本不适合,如果某些文件名包含空格(它假定wc输出中的第二个字段是整个文件名)。

$ cat bf.awk
$2 ~ /_V[0-9]+/ {
    lines = $1;
    file = $2;
    base = file;
    sub("_.*", "", base);
    if (lines > max[base]) {
        max[base] = lines;
        best[base] = file;
    }
}

END { for (base in best) print best[base] }


$ wc -l *_V*
       3 a_V1
       1 a_V2
       4 a_V3
       4 b_V1
       3 b_V2
       1 b_V3
       2 b_V4
      18 total


$ wc -l *_V* | awk -f bf.awk
a_V3
b_V1

答案 1 :(得分:1)

wc -l filename_V1 filename_V2 filename_V3 myFile_V1 myFile_V2 myFile_V3 | \
sort -rg

“计算每个文件的行数”|“按数字”|“逆序排序”

它还会打印总数(应该是最大数量),但这应该足够了。

这是一个单行。我使用\分隔符使其更清晰

混合物:

command_that_spits_files | xargs wc -l | sort -rg
find . -name 'filename_V[0-9]\{1,2\}' | xargs -L1 wc -l | sort -rg | cut -d ' ' -f 2

答案 2 :(得分:1)

如果您不想要sort,可以使用awk查找最大值,因为这也会报告行数,而不仅仅是最长文件的名称(按行数)。

wc -l filename_v1 filename_v2 filename_v3 | awk '$2 != "total" {if($1 > max_val) {max_val=$1; max_file=$2}}0; END{print max_file}'

所以我们会做一个wc -l来获取我们感兴趣的任何文件集中的行数,然后在awk中我们将跟踪我们看到的最大数字在第一个值并存储它,然后在最后打印出与我们看到的最大行数相关的文件名。

为了好的衡量标准,我们不计算“总计”行数

找到所有文件的最安全的方法就是这样做(使用GNU wc):

find -type f -name '*_V*' -print0 | wc -l --files0-from=- | awk '$2 != "total" {if($1 > max_val) {max_val=$1; max_file=$2}}0; END{print max_file}'

或没有GNU的wc:

find -type f -name '*_V*' -print0 | xargs -0 wc -l | awk '$2 != "total" {if($1 > max_val) {max_val=$1; max_file=$2}}0; END{print max_file}'

并在find中为-name使用适当的文件glob。此外,如果您不想查看子目录,请添加-maxdepth 1

答案 3 :(得分:1)

LARGESTFILE=;MAXLINECOUNT=0;for file in *; do CURRENTCOUNT=$(wc -l <"$file"); if [ "$CURRENTCOUNT" -gt "$MAXLINECOUNT" ]; then LARGESTFILE=$file; MAXLINECOUNT=$CURRENTCOUNT; fi; done; echo $LARGESTFILE

答案 4 :(得分:1)

另一个“一个班轮”:

git

这假设文件名中没有制表符或换行符,并使用了许多基础(cmake转义字符,字符串操作)。与此处的大多数答案不同,它不会在文件名中阻塞空格或多次出现# generate a tab seperated table: name|basename|lines for f in *_V[0-9]*;do printf "$f\t${f%V*}\t%d\n" $(wc -l < "$f");done |\ sort -t$'\t' -k3rn |\ # sort rows by line number descending sort -t$'\t' -u -k2,2 |\ # take rows with unique basename in sorted order cut -f1 # take name column

更高效的版本

原始版本很强大,但生成表格会调用$_ N 次。这个有点丑,但更快(在我的机器上200倍):

printf

答案 5 :(得分:1)

替代很多管道

wc -l *_V* | \             # generate the list
sed 's/_V/ _V/;$d' | \     # separate baseline from versions, delete total
sort -k 2,2 -k 1,1nr | \   # sort by names and size (reverse)
sort -k 2,2 -u | \         # get the first by name (max by design)
sed 's/ _V/_V/' | \        # reverse baseline name back to original
awk '{print $2}'           # extract the filename

此脚本假定文件名在您的控制范围内,并且_V不会出现在基本名称中。否则请查看@ Qualia的版本。

答案 6 :(得分:0)

使用GNU awk for BEGINFILE:

awk '
BEGINFILE { base=FILENAME; sub(/_[^_]+$/,"",base); fname[base]; max=0 }
FNR > max { max=FNR; fname[base]=FILENAME }
END { for (base in fname) print fname[base] }
' *

您可以使用FNR==1而不是BEGINFILE在非gawk中进行近似,但是如果可能的话,您需要额外的代码来处理具有给定基数的所有文件都为空的情况。 / p>