有没有办法找到目录中所有文件共享的行?

时间:2019-02-15 09:03:24

标签: bash

我需要您的帮助来解决bash中的问题。我开始使用它,现在只需要提取文件夹中所有文件中共有的单词(在第二列中)。我了解它仅适用于两个文件,但不适用于所有这些文件。 这是我脚本的开头:

for file in *
do
    awk '{print $2}' $file | sort -n > ord/$file
done

以上几行用于提取和排序第二列,但是现在我不知道如何只查找所有文件中的单词。

4 个答案:

答案 0 :(得分:2)

这是一个简单的Awk脚本,用于打印所有文件中存在的$2的所有值。

awk '# Count number of files; no lines were seen in this file yet
    FNR==1 { file++; delete b }
    # If not already seen in this file, add one to count
    # and mark as seen in this file as a side effect
    !b[$2]++ { a[$2]++ }
    # In the end, print all values which occurred in all files
    END { for (k in a) if (a[k]==file) print k }' *

这将检查当前目录中的所有文件。您可以在末尾用任何与要检查的文件集匹配的通配符替换通配符。

删除注释后,这可能是一个单行,尽管我们不要作弊太多。这里有两条线:

awk 'FNR==1 { file++; delete b }  !b[$2]++ { a[$2]++ }
    END { for (k in a) if (a[k]==file) print k }' *

答案 1 :(得分:1)

所有文件的通用提取行

以下递归命令提取所有文件通用的。优点是我们不必对任何东西进行排序。

intersect() { f="$1"; if shift; then grep -Fxf "$f" | intersect "$@"; else cat; fi; }
common() { f="$1"; shift; intersect "$@" < "$f"; }
common *

这里的窍门是递归相交文件。如果我们将文件理解为数学的行集,则问题归结为»给出给定集a,b,…,n,如何计算a b∩…n «。

我们可以使用与grep -Fxf a bcat b | grep -Fxf a相同的命令cat a | grep -Fxf b计算交集a∩b(为了更好的可读性,无用cat)。 a和b的顺序无关紧要。

要计算交集a b c,我们可以计算(a b)c。如何计算(a∩b)已经众所周知(请参见上文),因此我们对(a∩b)的结果应用相同的方法:cat a | grep -Fxf b | grep -Fxf c

应该从那里继续进行操作。

使用第二列代替整行

要仅使用第二列而不是整行,我们可以处理修改后的副本

for f in *; do
    awk '{ print $2 }' "$f" > "$f-col2"
done
common *-col2

…或调整功能

mask() { awk '{ print $2 }' "$@" }
intersect() { f="$1"; if shift; then grep -Fxf <(mask "$f") | intersect "$@"; else cat; fi; }
common() { f="$1"; shift; mask "$f" | intersect "$@"; }
common *

答案 2 :(得分:0)

尝试这样的事情:

$ FILES=`ls -1 *`
$ COUNT=`grep -c ^ <<<"$FILES"`
$ for FILE in $FILES; do awk '{ print $2}' $FILE | sort -u; done | \
     sort | uniq -c | grep " $COUNT "

分开来看,我们首先将文件列表放入FILES,然后将其中的文件数计数到COUNT中-在过程结束时使用。

然后,我们在每个文件的第二列中获取单词,并使用“ sort -u”返回每个单词中的一个。

我们对所有文件循环执行此操作,然后计算每个单词出现的次数。这使用“ uniq -c”显示以字数为前缀的字。因此,如果单词“ pepper”出现在7个文件中,则循环为这7个文件中的每一个输出“ pepper”一次,而“ uniq -c”输出“ 7 Pepper”(始终在开头有空格)。如果文件总数为7,那么我们现在知道每个文件在第二列中至少有一个单词“ pepper”的实例。

我们知道文件数为COUNT。因此,我们只搜索具有“ 7”(两边有空格)的“ uniq -c”输出。

答案 3 :(得分:0)

这是另一个awk:

awk '(NR==FNR){a[$2]++; next}
     (FNR==1) { for(i in a) if (a[i]==0) delete a[i]; else a[i]=0; }
     ($2 in a) {a[$2]++}
     END { for(i in a) if (a[i]!=0) print i }' f1 f2 f3 f4 ...

这可以通过以下方式进行。我们跟踪保存所有常见条目的数组a。如果在文件中看到一个值,我们将增加数组的值。每次读取一个新文件时,我们都会检查哪些值仍为零,并将其从数组中删除:

  • (NR==FNR){a[$2]++; next} :读取第一个文件。使用所有值初始化数组a
  • (FNR==1) { for(i in a) if (a[i]==0) delete a[i]; else a[i]=0; }: 如果我们输入一个新文件(FNR==1),请检查数组a中的所有条目。如果该值仍为0,则表明我们在上一个文件中未遇到数组a的键,因此将其删除。否则,将其重置为零以开始下一个循环。
  • ($2 in a) {a[$2]++}:此处,我们处理文件的每一行。如果条目位于数组a中,则将其递增。这意味着所有不常见的值仍将具有值0,其他值将更高。
  • END { for(i in a) if (a[i]!=0) print i }:在所有处理结束时,打印剩余的内容。