2

grep を使用して、特定の文字セットを持つ辞書ファイルから単語の出現を検索する方法。各文字は 1 回だけ出現するという制限があります。

EG 文字が abc の場合、予想される出力は次のようになります。

タクシー


編集:

辞書ファイル (Mac OS X オペレーティング システムのように 1 行に 1 単語を含むファイル/usr/share/dict/words) と (一意の) 文字のセットが与えられた場合、入力の各文字を含む辞書ファイルのすべての単語を出力したいと考えています。一度だけ設定します。たとえば、文字のセットがセットの{a,b,c}各文字を含むすべての (3 文字の) 単語を出力する場合。

できれば、grep 式だけを使用するソリューションを探しています。

4

4 に答える 4

1

たとえばabc、一連の文字を指定すると、次のようにそれぞれを先読みに変換できます。

^(?=[^a]*a[^a]*)(?=[^b]*b[^b]*)(?=[^c]*c[^c]*)$

-Eでこの正規表現を使用するには、「拡張正規表現」フラグを使用する必要がある場合がありますgrep


文字列からこの正規表現を作成するには、次を使用できますsed(読者の演習)

于 2013-03-05T18:58:34.263 に答える
0

私が見つけた解決策は、grepfirst を使用して、入力セットから文字のみを含む n 文字の単語をすべて抽出することです。(ここでも、入力文字は一意であると想定しています)。次に、一連の 1-lettergrepsを実行して、各文字が少なくとも 1 回出現するようにします。単語の長さは n であるため、これにより、単語に各文字が 1 回だけ含まれることが保証されます。たとえば、入力文字セットが(a,b,c}次の場合、解決策は次のようになります。

grep -E '^[abc]{3}$' /usr/share/dict/words | grep a | grep b | grep c

grep$1 を入力文字セットとして使用して、この文字列を作成し、単語ファイルに対して実行する単純な bash スクリプトを作成できます。文字列を生成する最も効率的な方法ではないかもしれませんが、私は慣れていないsedawk、問題を解決しているようです。私が作成したスクリプトは次のとおりです。

#!/bin/sh
slen=${#1}
g2="'^[$1]{$slen}\$'"
g3=""
ix1=0
while [ $ix1 -lt $slen ]
do
  g3="$g3 | grep ${1:$ix1:1}"
  ix1=$((ix1+1))
done
eval grep -E $g2 /usr/share/dict/words $g3
于 2013-03-08T00:51:46.030 に答える
0

以下はPerlのソリューションです。辞書にさらに単語を追加し、入力を$input変数に読み込む必要があることに注意してください。有効な単語の配列は になります@results

#!/usr/bin/env perl

use Data::Dumper;

my $input = "abc";

my @dictionary = qw(aaa aac aad aal aam aap aar aas aat aaw aba abc abd abf abg
  abh abm abn abo abr abs abv abw aca acc ace aci ack acl acp acs act acv ada adb
  adc add adf adh adl adn ado adp adq adr ads adt adw aea aeb aec aed aef aes aev
  afb afc afe aff afg afi afk afl afn afp aft afu afv agb agc agl agm agn ago agp
  ...

  PUT A REAL DICTIONARY HERE!

  ...
  zie zif zig zii zij zik zil zim zin zio zip zir zis zit ziu ziv zlm zlo zlx zma
  zme zmi zmu zna zoa zob zoe zog zoi zol zom zon zoo zor zos zot zou zov zoy zrn
  zsr zub zud zug zui zuk zul zum zun zuo zur zus zut zuz zva zwo zye zzz);

# Generate a lookahead expression for each character in the input word
my $regexp = join("", map { "(?=.*$_)" } split(//, $input));

my @results;
foreach my $word (@dictionary) {

  # If the size of the input doesn't match the dictionary word, skip to the
  # next word.
  if (length($input) != length($word)) {
    next;
  }

  if ($word =~ /$regexp/) {
    push(@results, $word);
  }
}

print Dumper @results;
于 2013-03-04T19:31:30.020 に答える