【问题标题】:How to display words as per given number of letters?如何根据给定的字母数显示单词?
【发布时间】:2017-03-17 10:13:14
【问题描述】:

我已经创建了这个基本脚本:

#!/bin/bash

file="/usr/share/dict/words"
var=2
sed -n "/^$var$/p" /usr/share/dict/words

但是,它并没有按要求工作(或者仍然需要一些更多的逻辑来添加它)。

在这里,它应该只打印 2 个字母的单词,但它会给出不同的输出

任何人都可以提出如何使用 sed 或 awk 实现这一点的想法吗?

【问题讨论】:

  • 顺便说一下,$file 变量在这里看起来没用,因为您稍后在 sed 调用中不会使用它。

标签: regex linux bash awk sed


【解决方案1】:

它应该只打印 2 个字母的单词

您的sed 命令只是在文本中搜索带有2 的行。

您可以为此使用awk

awk 'length() == 2' file

或者使用shell变量:

awk -v n=$var 'length() == n' file

【讨论】:

  • 非常适合 awk 长度函数
  • length 默认作用于$0,所以也可以使用awk 'length==n'
  • 非常好的点@Sundeep。我忘记了,现在编辑它。
  • 刚查到gawk doc for length...推荐length()
【解决方案2】:

你正在执行的是:

sed -n "/^2$/p" /usr/share/dict/words

这意味着:所有行都恰好包含数字 2,仅此而已。当然这不会返回任何东西,因为/usr/share/dict/words 有单词而不是数字(据我所知)。

如果要打印包含两个字符的行,则需要使用 .. 之类的内容(因为 . 匹配任何字符):

sed -n "/^..$/p" /usr/share/dict/words

要使字符数可变,请使用量词{} like(注意\ 的用法以正确理解sed 的BRE):

sed -n "/^.\{2\}$/p" /usr/share/dict/words

或者,使用变量:

sed -n '/^.\{'"$var"'\}$/p' /usr/share/dict/words

请注意,为了安全起见,我们将变量放在引号之外(感谢 cmets 中的 Ed Morton 的提醒)。

【讨论】:

  • +1。 FWIW 我总是尽量本地化 shell 变量扩展,例如sed -n '/^.\{'"$var"'\}$/p' 以避免在脚本的其余部分由 shell 解释时出现任何意外。
  • @EdMorton 谢谢!在这种情况下会发生什么?我的意思是,在哪些情况下我的方法可能会出现意外行为?
  • 您的特定脚本会很好,但通常最好防止出现问题。就像引用 shell 变量一样——在许多情况下这并不重要,但最好养成在重要的时候这样做的习惯。
【解决方案3】:

纯 bash... :)

file="/usr/share/dict/words"
var=2

#building a regex
str=$(printf "%${var}s")
re="^${str// /.}$"

while read -r word
do
    [[ "$word" =~ $re ]] && echo "$word"
done < "$file"

它以^..$ 的形式构建一个正则表达式(点的数量是可变的)。所以分两步完成:

  • 创建所需长度的字符串,例如:%2s。没有参数 printf 仅打印所需长度的填充空间,例如:2
  • 但我们有一个变量var,因此%${var}s
  • 将字符串中的所有空格替换为.

但不要使用此解决方案。它太慢了,这里有更好的实用程序,最好是恕我直言grep

file="/usr/share/dict/words"
var=5

grep -P "^\w{$var}$" "$file"

【讨论】:

  • +1 用于带有正则表达式的 bash 脚本,但你能解释一下正则表达式变量 str=$(printf "%${var}s") -> 为什么 s 最终存在? re="^${str// /.}$" -> 这里,给定 1 或 2 多少个空格?
【解决方案4】:

试试awk-

awk -v var=2 '{if (length($0) == var) print $0}' /usr/share/dict/words

这可以缩短为

awk -v var=2 'length($0) == var' /usr/share/dict/words

效果相同。

【讨论】:

    【解决方案5】:

    使用 grep 仅输出匹配 2 个字母字符的行:

    grep '^[[:alpha:]]\{2\}$' /usr/share/dict/words
    

    【讨论】:

      【解决方案6】:

      GNU awk 和 mawk 至少(由于空 FS):

      $ awk -F '' 'NF==2' /usr/share/dict/words                  #| head -5
      aa
      Ab
      ad
      ae
      Ah
      

      空的FS 将每个字符分隔在自己的字段中,因此NF 告诉记录长度。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-09-25
        • 2013-02-15
        • 2022-12-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多