「ファイル」というテキストファイルがあります。 「this is」と「is this」が等しいと見なされる最も一般的な2つの単語シーケンスを見つけるには、awkを使用する必要があります。
テキスト例:私の名前はで、これは次のテキストです。
期待される出力: 3 か。
私はこのループを使用しました:
awk 'BEGIN{
for(i=1;i<NF;i++)
a[$i OFS $(i+1)]++
}' file
なぜこれが失敗するのか知っている人はいますか?
答え1
ファイルを読み取らないため、コードは失敗します。特殊BEGIN
ブロックが実行されます。今後コマンドラインに名前が付けられた最初の入力ファイルも読み取り用に開きます(END
最後のファイルの次のブロックも同じです)。また、コードの出力はありません。
他のユーザーはすでに独自のソリューションを提供しているので、コードをインポートして少し修正します。
- 入力の各行に対して実行されるように、通常のブロックでコードを実行します。
- ブロックを使用して
END
配列内で最も一般的な単語の組み合わせを見つけ、すべての入力が処理された後に出力します。 - 各ペアの単語が常にアルファベット順に使用されていることを確認してください。
awk '
{
for (i = 1; i < NF; i++)
if ($i < $(i+1)) a[$i OFS $(i+1)]++
else a[$(i+1) OFS $i]++
}
END {
for (words in a)
if (a[words] > a[m]) m = words
print m, a[m]
}' file
与えられた入力に従って印刷されますis this 3
。
別の実装は、ファイルの読み取り中に最大値を追跡し、最後に印刷することです。
awk '
{
for (i = 1; i < NF; ++i) {
if ($i < $(i+1)) words = $i OFS $(i+1)
else words = $(i+1) OFS $i
if (++count[words] > count[m]) m = words
}
}
END { print m, count[m] }' file
配列について心配しないでください。
awk '{ for (i = 1; i < NF; ++i) if ($i < $(i+1)) print $i, $(i+1); else print $(i+1), $i }' file | sort | uniq -c | sort -n | tail -n 1
つまり、awk
単語の組み合わせを生成(1行に1つずつ)を使用してソートし、それぞれの発生回数を取得してソートします。これら(数に基づいて)最も高い数を選択してください。大きなデータを呼び出してsort
電子メールなどの小さなデータを実行するのは高価ですが、十分です。
答え2
努力する:
gawk '{
for (i=2; i<=NF; i++) {
delete arr; split($(i-1) "\n" $i, arr);
asort(arr); s[arr[1] FS arr[2]]++
};
}
END { for(x in s) print s[x], x }' infile |sort -nr
3 is this
2 my name
1 our text
1 is text
1 is our
1 is name
split()
この関数は、スペース(タブ/スペース)で区切られた文字列のペアを配列に追加しますarr
が、各文字列は別々の行にあります\n
。
asort()
関数はarr
その配列をソートします。次に、ソートされた文字列ペアとしてキーを使用して呼び出される別の配列に結果を追加しs
、再度発生すると、同じ文字列ペアごとに値が増加します。
delete arr
arr
次のフィールドペアを処理するために配列を削除します。
END
配列要素を繰り返しs
、ペア自体とともに表示される各要素ペアの数を印刷した後、結果がソートされ、最もsort -nr
繰り返される文字列ペアが得られます。
is this
注:結果はほとんどまたは全体があるかどうかを知らせず、それらのうちの1つのみを示し、この例の結果はすべてのソートさthis is
れた結果のみを示します。is this
答え3
@kusalanandaが指摘したように、最大の間違いはすべてのコードをBEGINブロックに入れることです。したがって、"this is" and "is this" are considered equal in our count.
入力に表示される相対的な順序に関係なく、出会うすべての単語のペアが特定の(並べ替えられた)順序で保存されるようにするには、次の作業を実行する必要があります。
awk '
{
for(i=1; i<NF; i++) {
pair = ($i > $(i+1) ? $i OFS $(i+1) : $(i+1) OFS $i)
c = ++cnt[pair]
max = (max > c ? max : c)
}
}
END {
for (pair in cnt) {
c = cnt[pair]
if ( c == max ) {
print pair, c
}
}
}
' file
this is 3