【问题标题】:Unable to make a factorial function in AWK无法在 AWK 中创建阶乘函数
【发布时间】:2010-10-21 17:34:44
【问题描述】:

代码

 #!/usr/bin/awk            

 # Sed and AWK by O'Reilly (p.179)

 # Example of what should happen: factorial 5 gives
 #   factorial
 #   Enter number: 3
 #   The factorial of 3 is 6


 BEGIN {
     printf("Enter number: ")
 }

 $1 ~ /^[0-9]+$/ {
     # assign value of $1 to number & fact
     number = $1 
     if (number == 0) 
         fact = 1
     else
         fact = number

     for (x = 1; x < number; x++)
         fact *=x
     printf("The factorial of %d is %g\n", number, fact)

     exit
 }

 # if not a number, prompt again.
 { printf("\nInvalid entry. Enter a number: ")
 }

我运行命令失败

./factorial.awk

我明白了

/usr/bin/awk: syntax error at source line 1
 context is
         >>>  <<< ./factorial.awk
/usr/bin/awk: bailing out at source line 1

错误信息是什么意思?

【问题讨论】:

  • 输入 'sudo apt-get install gawk' 然后 ./factorial.awk
  • 我的电脑里有 3.1.5 GAWK。

标签: awk factorial


【解决方案1】:

我认为问题在于您正在编写一个 shell 脚本并将其传递给 awk 执行。以下是一个 shell 脚本,因此是 #! /bin/sh,因此它将被传递给 shell(在这种情况下与 Bourne 兼容)。

#! /bin/sh
awk 'BEGIN { printf("Hello world!\n"); exit }'

she-bang (#!) 行告诉当前解释器将脚本传递给哪个解释器执行。您必须将脚本传递给awk 解释器,因此您需要显式调用awk。这假设 awk 在您的路径中的某处。

然而,下面是一个awk 脚本。

#! /usr/bin/awk -f
BEGIN {
    printf("Hello world!\n");
    exit
}

she-bang 调用 awk 并将脚本作为输入传递。在这种情况下,您不需要显式调用awk,也不需要引用整个脚本,因为它直接传递给awk

将 she-bang 想象为 获取 she-bang 之后的内容,附加文件名,然后执行它Wikipedia 很好地描述了用法,包括一些解决 path to the interpreter 问题的常用方法。

【讨论】:

    【解决方案2】:

    可能是一个愚蠢的答案,但在我的终端中我必须输入:

    ./factorial.awk
    

    文件是 factorial.awk。

    您可以编辑路径环境变量以包含 .但是 ./ 我认为应该可以正常工作。并添加 .在某些情况下,你会运行你没想到的代码,到 $PATH 可能会被证明是非常危险的。

    这样行吗??

    编辑:

    ./factorial.awk -bash: ./factorial.awk: /usr/bin/gawk: 错误的解释器:没有这样的文件或目录

    这表示它运行了文件但找不到程序 gawk。 请输入“which gawk”,然后输入“which awk”。

    你的第一行应该是:

    #!/usr/bin/awk
    

    另外,为了逗我开心,输入:

    sudo apt-get install gawk
    

    这将确保您的系统实际上有 gawk。

    编辑2: 我看了你的代码,这就是我现在所拥有的。我删除了两个引号和一个破折号。

    #!/usr/bin/gawk                                                                                                                                        
    
    # I think we do not need these (p.179) so I comment them out, since I do not know where else to put them.
    # The same bug occurs also with them.
    #fact = number
    #for (x = number -1 ; x > 1; x--)
    #    fact *= x
    
    awk # factorial: returns factorial of user-supplied number
        BEGIN {
        printf("Enter number: ")
        }
    
       $1 ~ /^[0-9]+$/ {
       # assign value of $1 to number & fact
       number = $1 
       if (number == 0) 
           fact = 1
       else
           fact = number
       #loop to multiply fact*x until x = 1
       for (x = number - 1; x > 1; x--)
           fact *= x
       printf("The factorial of %d is %g\n", number, fact)
       #exit -- saves user from typing ^-d
       exit
    }
    
    # if not a number, prompt again.
    { printf("\nInvalid entry. Enter a number: ")
    }
    

    【讨论】:

    • dpaste.com 示例显示您使用 'sudo' 运行 'chmod';这是一套危险的做法。在您灾难性地破坏您的系统之前,立即摆脱它们。对于您编写的脚本,永远不需要使用 sudo 来更改权限。您应该在自己的领域内使用自己的文件工作,您可以在不需要 root 权限的情况下更改权限。
    • @Jonathan:感谢您提供的信息!我有过在开始调试时先降低权限的做法。
    • 我提供的代码可以在我的机器上运行,但这并不能说明什么。我希望它对你有用。
    【解决方案3】:

    可能没那么复杂。

    #!/usr/bin/awk ---------> #!/usr/bin/awk -f

    【讨论】:

      【解决方案4】:

      检查是否有文件/usr/bin/gawk;如果没有,请使用 awk 的路径或 gawk 的正确位置。

      另外,您是否使脚本可执行?

      另外,你的 PATH 中有当前目录吗?

      【讨论】:

      • 代码现在是 777。你怎么知道我的 PATH 中是否有当前目录?
      • 好吧,如果 PATH=":/bin:/usr/bin:.:/home/me/bin:" 和当前目录 (cwd) = /home/me/bin,那么出现 cwd路径上的 4 次: (1) 在第一个冒号之前 (2) 作为两个冒号之间的点 (3) 作为 /home/me/bin (4) 在最后一个冒号之后。不要使用777权限;永远不要让文件——尤其是可执行文件——可公开写入;担心您的小组成员是否也应该拥有写权限。 (可能会更糟;我知道一个将 perms 设置为 7777 的生成文件(setuid、setgid、sticky bit!)
      • 由于输入“./factorial.awk”会引发错误“bash: ./factorial.awk: /usr/bin/gawk: bad interpreter: No such file or directory”,我认为您的机器没有程序 /usr/bin/gawk - 正如我的回答中所建议的那样。找到它...使用'which gawk',如果不能产生答案,则使用'which awk'。如果您获得了路径,请使用它来代替 /usr/bin/gawk。如果你没有得到路径,那么 awk 和 gawk 都不会安装在你 PATH 上的目录中。 ...继续...
      • 信不信由你,这是相当大的进步。你现在得到的是 awk 说“我不懂 shell 脚本”。 ...多说;生活介入!
      • OK - 将 awk 和单引号放在顶部附近;将匹配的单引号和尾随破折号放在底部。应该这样做。
      【解决方案5】:

      我通过运行让脚本在 Ubuntu 和 OS X 中运行

      awk -f factorial.awk
      

      虽然书上这么说,但您似乎无法按如下方式运行脚本

      ./factorial.awk 
      

      【讨论】:

      • 您当然可以将其作为“./factorial.awk”运行。执行此操作的要求是:(1)它可由用户执行,因此“chmod 0700 factorial.awk”,(2)文件的第一行是“#!/path/to/awk”,因此 shell 将运行awk,(3) 脚本在 shell 中相对于路径正确执行,因此 "./factorial.awk" 将起作用,并且 (4) 它是一个有效的 awk 脚本。将整个脚本包裹在“awk ' ... '”中是无效的!
      【解决方案6】:

      这是一个递归版本:

      #!/usr/bin/awk -f
      function f(x) {
          if (x <= 1) return 1
          return (f(x-1) *x)} 
      
      BEGIN {
          printf("Enter number: ")
      }
      
      $1 ~ /^[0-9]+$/ {
          printf("The factorial of %d is %d\n", $1, f($1))
          exit
      }
      
      { printf("\nInvalid entry. Enter a number: ")
      }
      

      【讨论】:

        【解决方案7】:

        这个问题是谷歌搜索短语“awk factorial”的热门问题,所以这里有一个在 awk 中打印阶乘的简单方法:

        $ awk 'BEGIN{x=1;for(i=2;i<=6;i++)x*=i;print x}'
        720
        

        作为一个shell函数(-v后面的空格是macOS自带的nawk需要的,gawk不需要):

        $ fac(){ awk -v "n=$1" 'BEGIN{x=1;for(i=2;i<=n;i++)x*=i;print x}';}
        $ fac 6
        720
        

        作为计算 k 组合的 awk 函数:

        $ awk 'function f(x){r=1;for(i=2;i<=x;i++)r*=i;return r}BEGIN{n=5;k=3;print f(n)/(f(k)*f(n-k))}'
        10
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-01-26
          • 2021-01-17
          • 1970-01-01
          相关资源
          最近更新 更多