如何使用 grep、sort 和 uniq 创建三个输出字段

如何使用 grep、sort 和 uniq 创建三个输出字段

我在命令中使用两个文件,第一个文件 ( file1) 只是一个文件,其中字母表中的每个字母都位于单独的行上。第二个文件($w在我的命令中)是一个巨大的单词列表。我必须将字母表列表与单词列表进行比较,以找到包含字母表中的字母两次的单词,显示每个字母有多少个单词,以及一个示例单词。输出会是这样的,但是对于整个字母表

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只会计算 uniq 实例,所以它会给你每个单词的计数,而不是传递给它的所有单词的计数,然后你只获取第一个输出。

答案2

从扎卡里·布雷迪版本开始:

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 (example ^[^a]*a[^a]*a[^a]*$)
  • grep -c ... 统计匹配单词的数量
  • grep -m 1 ... 获取第一个匹配的单词
  • Paste - - - ... 将 3 条输出行合并为一行

如果您喜欢随机单词示例,请将第二个 grep 替换为

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

“确保恰好两个”的另一种选择是找到 2 个 aa 并拒绝如果 aaa:

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

答案3

这里有两种方法可以做到这一点,一种是面向 shell 的(主要使用 grep),另一种是使用 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 按指示准备(每行一个字母),则初始排序和 uniq 是不必要的,但我无缘无故地添加了它们以更接近“使用 grep 排序和 uniq”要求。

awk的解决方案:

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

相关内容