grep、sort、およびuniqを使用して3つの出力フィールドを作成する方法

grep、sort、およびuniqを使用して3つの出力フィールドを作成する方法

私のコマンドは2つのファイルを使用していますが、最初のファイル(file1)はアルファベットの各文字が別々の行にあるファイルです。 2番目のファイル($w私のコマンドでは)は巨大な単語のリストです。アルファベットリストと単語リストを比較して、アルファベット文字を2回含む単語を見つけ、各文字の単語数とサンプル単語を表示する必要があります。出力は次のとおりですが、アルファベット全体について

v 94 bivalve
w 94 awkward
x 3 executrix
y 196 abysmally
z 58 bedazzle

以下は私のコマンドとその結果です

 for i in `cat file1`; do grep $i.*$i $w | sort | uniq -c | head -1; done
  1 aardvark    
  1 abba
  1 acacia
  1 abandoned
  1 abalienate
  1 affability
  1 ageing
  1 aforethought
  1 abalienation
  1 hajj
  1 backstroke
  1 abnormally
  1 accommodate
  1 abalienation
  1 abdominous
  1 agitprop
  1 quinqevalent
  1 aardvark
  1 abbess
  1 abatement
  1 absquatulate
  1 bivalve
  1 awkward
  1 executrix
  1 abysmally
  1 bedazzle

答え1

比較的新しいバージョンを使用すると仮定すると、bash同様のことができます。

for CHAR in {a..z}
do
    WORD_LIST=( $(grep "$CHAR.*$CHAR" $w) )
    echo $CHAR ${#WORD_LIST[@]} ${WORD_LIST[0]}
done

私たちはサイズの数を提供するbash配列を使用しており、配列${#WORD_LIST[@]}の最初の要素を取得しています${WORD_LIST[0]}

あなたの例がうまくいかないのは、一意のインスタンスのみを計算するuniq -cため、渡されたすべての単語の数ではなく各単語の数を提供し、最初の出力のみを取得できるからです。

答え2

Zachary Bradyバージョンから始める:

for i in {a..z} 
 do 
   ( echo $i ;
     grep -c    "^[^$i]*$i[^$i]*$i[^$i]*$" file1; 
     grep -m 1  "^[^$i]*$i[^$i]*$i[^$i]*$" file1
   ) | paste - - - 
 done
  • "^[^$i]*$i[^$i]*$i[^$i]*$"正確に2回発生することを確認することです$i (例^[^a]*a[^a]*a[^a]*$)。
  • grep -c ... 一致する単語数を計算します。
  • grep -m 1 ... 最初に一致する単語を取得します。
  • 貼り付け - - - ... 3本の出力ラインを1つにマージ

ランダムな単語の例を好む場合は、2番目のgrepを次に置き換えます。

grep "^[^$i]*$i[^$i]*$i[^$i]*$" file1 | shuf | head -1

「正確に2つあることを確認する」もう1つのオプションは、2 aaを見つけてaaaの場合は拒否することです。

grep 'a.*a' file1  | grep -vc 'a.*a.*a' 

答え3

これを行う方法は2つあります。 1つはシェル指向(主にgrepを使用)、もう1つはawkを使用することです。

w=/usr/share/dict/words
sort file1 | uniq | while read letter
do
  count=$(grep -ic "^[^$letter]*$letter[^$letter]*$letter[^$letter]*$" "$w")
  r=$(( (RANDOM % count) + 1 ))
  printf "%s %d %s\n" "$letter" $count \
    $(grep -i "^[^$letter]*$letter[^$letter]*$letter[^$letter]*$" "$w" | \
        sed -n ${r}p )
done

file1が指示どおりに(1行に1文字ずつ)準備されている場合、初期ソートとuniqは必要ありませんが、「ソートとuniqでgrepを使用する」要件に近づくために何の理由もなく追加されました。

奇妙な解決策:

BEGIN {
  split("abcdefghijklmnopqrstuvwxyz", alphabet, "");
  srand();
}
{
  for (i in alphabet) {
    letter=alphabet[i]
    if (match(tolower($1), "^[^"letter"]*"letter"[^"letter"]*"letter"[^"letter"]*$")) {
      counts[letter]++
      if (wordfor[letter]) {
        if (rand() * counts[letter] >= counts[letter] - 1)
          wordfor[letter]=$1
      } else
        wordfor[letter]=$1
    }
  }
}
END {
  for (i in alphabet)
    print alphabet[i], counts[alphabet[i]], wordfor[alphabet[i]]
}

ファイルに保存し、次のように使用します。

w=/usr/share/dict/words ## or whatever
awk -f theabove.awk "$w" | sort

関連情報