这里有一个示例文本文件:
word1 word2 word3 word4
word4 word5 word6 word7
word6 word7 word8 word9
word9 word6 word8 word3
word1 word4 word5 word4
提取前一行N个常用词的行是什么命令?
在示例文件中,将输出包含3个常见的不同单词的行并与前一行一起输出:
word9 word6 word8 word3
注意:使用编程语言(提取array_sentence1.uniq和array_sentence2.uniq)很容易,但是我使用sed / awk搜索解决方案。
答案 0 :(得分:2)
$ cat tst.awk
{
delete seen
cnt = 0
for (i=1; i<=NF; i++) {
word = $i
cnt += ( !seen[word]++ && prev[word] ? 1 : 0 )
}
if (cnt >= 3) {
print
}
delete prev
for (word in seen) {
prev[word]++
}
}
$ awk -f tst.awk file
word9 word6 word8 word3
答案 1 :(得分:1)
这是AWK中的解决方案:
▶ cat > FILE <<EOF
word1 word2 word3 word4
word4 word5 word6 word7
word6 word7 word8 word9
word9 word6 word8 word3
word1 word4 word5 word4
EOF
我的原始解决方案在这里。假设每行中的单词都是唯一的。
# script.awk
NR > 1 { # On lines other than the first:
split(last, last_ar) # Split the last record and the
split($0, curr_ar) # current record.
found = 0 # Count how many words curr_ar
for (i in curr_ar) # and last_ar have in common.
for (j in last_ar)
if (last_ar[j] == curr_ar[i])
found++
if (found >= 3) print # ... and print this record
# if 3 or more were found.
}
{
last = $0 # On all lines.
}
要处理唯一性,我有一个经过修改的解决方案,该解决方案使用GNU AWK的length函数(在Mac OS X上也是如此)
# script.gawk
NR > 1 {
split(last, last_ar)
split($0, curr_ar)
delete found # Count how many unique occurrences
for (i in curr_ar) # of words are seen.
for (j in last_ar)
if (last_ar[j] == curr_ar[i])
found[curr_ar[i]]++
if (length(found) >= 3) print
}
{
last = $0
}
测试:
▶ gawk -f script.gawk FILE
word9 word6 word8 word3
答案 2 :(得分:1)
您可以使用哈希确保唯一值,这是一个示例脚本:
parse.awk
# Only start checking from the second line
NR > 1 {
c = 0 # Variable to hold the common word count
# Run through unique words and compare to previous line
for(i=1; i<=NF; i++) {
if( $i in h && !($i in g) ) {
c++
g[$i]
}
}
# Reset the associative arrays
delete h
delete g
}
# If we had enough matches print the current line
c >= N
# Collect current line into the h associative array
{
for(i=1; i<=NF; i++)
h[$i]
}
像这样运行它:
awk -f parse.awk N=3 infile
输出:
word9 word6 word8 word3
答案 3 :(得分:1)
这可能对您有用(GNU sed):
sed -nE 'N;h;s/(.*)(\n.*)/\n\1 \2 /;:a;s/(\n(\S+\s+).*\n.*)\2/N\1/;s/\n\S+\s+/\n/;ta;/^N{3}/{g;s/.*\n//p};g;D' file
解决方案包括三个部分:
第一部分
启动了两行移动的窗口。
制作包含原始2行窗口的原始模式空间的副本。
在模式空间前添加换行符,并在两行的末尾添加其他空格。换行符用作唯一单词计数的分隔符,空格允许每行中的最后一个单词匹配。
第二部分
引发了模式匹配循环,其中第一个单词及其后续空格与第二行中的任何单词匹配。如果匹配,则从第二行中删除该单词,并在引入的换行符之前增加一个计数器。删除第一行中的第一个单词,并重复该过程,直到第一行中没有其他单词为止。
检查计数器所需的匹配数,如果发现为真,则刷新模式空间的副本,删除第一行,并打印第二行。
第三部分
无论如何,都将刷新模式空间,删除第一行,并重复该过程直到文件结束。
上面的解决方案打印出N个或更多匹配项的行(在上面的解决方案中,如OP的示例中N设置为3),因为只有N个匹配项使用:
sed -nE 'N;h;s/(.*)(\n.*)/\n\1 \2 /;:a;s/(\n(\S+\s+).*\n.*)\2/N\1/;s/\n\S+\s+/\n/;ta;/^N{3}\n/{g;s/.*\n//p};g;D' file
答案 4 :(得分:0)
一种方法:
$ awk '{x=0;for(i=1;i<=NF;i++)if ($i in a)x++;split("",a);for(i=1;i<=NF;i++){a[$i]};}x==3' file
word9 word6 word8 word3
将行内容存储在关联数组中。然后检查关联数组并增加计数器x。
答案 5 :(得分:0)
替代解决方案:
awk '{
c=0;
for(i=1;i<=NF;i++)
{
if(l[$i]){c+=1}
}
}
{
delete l;
for(i=1;i<=NF;i++)
{
l[$i]=1
}
}
c>=3' <your file>
答案 6 :(得分:0)
$ echo '
> word1 word2 word3 word4
> word4 word5 word6 word7
> word6 word7 word8 word9
> word9 word6 word8 word3
> word1 word4 word5 word4
> ' | awk -v n=3 '
> NR == 1 { for (i = 1; i <= NF; i++) { word[$i]++ } }
> NR > 1 { counter = 0
> for (i = 1; i <= NF; i++) {
> if (word[$i]-- > 0) counter++ }
> if (counter >= n) print $0
> delete word
> for (i = 1; i <= NF; i++) { word[$i]++ } }
> '
word9 word6 word8 word3
答案 7 :(得分:0)
如果您的数据位于d
文件中,请在gnu awk上尝试
awk 'NR==1{for(;i++<NF;)a[i]=$i;next} {for(i=0;i++<NF;){for(j in a){if($i==a[j])c++;if(c==3){print;exit}}}; c=0;i=length(a);NF+=i;for(j=0;i<NF;)a[++i]=$++j} ' d