我需要您的帮助来解决bash中的问题。我开始使用它,现在只需要提取文件夹中所有文件中共有的单词(在第二列中)。我了解它仅适用于两个文件,但不适用于所有这些文件。 这是我脚本的开头:
for file in *
do
awk '{print $2}' $file | sort -n > ord/$file
done
以上几行用于提取和排序第二列,但是现在我不知道如何只查找所有文件中的单词。
答案 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 b
或cat 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 }
::在所有处理结束时,打印剩余的内容。