【问题标题】:awk: calling a function outside of awkawk:在 awk 之外调用函数
【发布时间】:2014-02-15 06:15:08
【问题描述】:

更新:

我正在开发一个模块化的 shell 脚本,它在不同级别的子进程中调用 usage()。脚本sample.sh 的结构如下:

sample.sh
├─ ...
├─ usage()
├─ awk
    ├─ usage()
├─ ...

usage() 显示有关如何使用脚本的简要信息(例如可用参数及其描述)。第一次执行时,usage() 会显示在脚本的开头。 usage() 调用的其他条件示例包括:

  1. awk 无法验证来自stdio 或文件的输入

  2. argument--help 被接收

  3. 发生了其他用户衍生的故障

我想从 shell 及其直接子进程 awk 调用相同的函数 usage()


原问题:

函数,usage() of sample.sh 根据需要打印其打印语句。

$cat sample.sh
#!/bin/sh
awk '
    BEGIN {
        usage()
    }
    function usage() {
        print "function inside of awk"
    }
'
$./sample.sh
function inside of awk

要从awk 中取出usage() 并将其作为本地函数放在sample.sh~ 中,我尝试了:

$cat sample.sh~
#!/bin/sh
usage() {
    print "function outside of awk"
}    
awk '
    BEGIN {
        usage()
    }
'
$./sample.sh~
awk: calling undefined function usage
 source line number 3

正如我们所观察到的,我们在sample.sh~ 中收到“未定义函数用法”的错误消息。我应该如何改进它?

【问题讨论】:

  • awk 不是外壳,就像 C 不是外壳一样。你不应该期望能够在 awk 之外调用一个 shell 函数,而不是你可以在 C 之外调用一个 shell 函数。如果你告诉我们你想要做什么(而不是你想怎么做),并带有一些示例输入和我们可以为您提供帮助。

标签: bash shell awk


【解决方案1】:

我找到了一种从 awk 中调用函数的方法

把下面的代码放到一个文件里,比如叫a.sh

$ cat a.sh
usage() {
  print "function outside of awk"
 }

$ chmod +x a.sh

那么就可以在awk中调用函数了

#!/bin/sh
awk '
    BEGIN {
       system(". a.sh;usage")
    }'

【讨论】:

    【解决方案2】:

    使用bash,另一种选择是导出带有export -f的shell函数,然后通过system()调用awk可以使用:

    #!/usr/bin/env bash
    
    usage() {
      echo "function outside of awk"
    }
    
    # Export the usage() function.
    export -f usage
    
    awk '
      BEGIN { 
        system("/usr/bin/env bash -c usage") 
      }'
    

    请注意,awk 使用 system() 调用 sh,这可能是也可能不是 bash - 如果它是 bash(例如,在 OSX 上),您并不严格需要 /usr/bin/env bash -c部分,但保留它应该可以在大多数平台(有 bash)上工作。

    【讨论】:

      【解决方案3】:

      子进程不能调用父进程中的函数,反之亦然。甚至不是同一种语言。

      您可以做的是启动另一个包含您的 awk 脚本的 shell 脚本实例。例如,将其保存在名为 ./script.sh 的脚本中:

      #!/bin/sh -e
      
      usage() {
          echo usage: ...
          exit 1
      }
      
      test "$1" = --usage && usage
      
      awk -v usage_script="$0" '
      function usage() { system(usage_script " --usage") }
      BEGIN {
          usage()
      }'
      

      使其可执行,并以./script.sh 运行。在此脚本中,内部awk 脚本中的usage 函数只是使用--usage 脚本重新运行包含的shell 脚本。请记住,这里将有 3 个进程:shell -> awk -> shell。在一个进程中不可能做到这一点。

      原答案

      如果将usage 函数定义移到awk 之外,则无法从内部执行是正常的。如果要执行awk 命令,则必须在awk 解释器中,并且只能使用其中定义的内容。

      请注意确定这是否是您要查找的内容,但您可以将函数定义移动到另一个 awk 文件并让 awk 处理它,例如:

      cat <<EOF > functions.awk
      function usage() {
          print "function in functions.awk"
      }
      EOF
      awk -f functions.awk -e '
          BEGIN {
              usage()
          }
      '
      

      【讨论】:

      • 感谢您的意见。请参阅我更新的问题。仅当usage() 显示专门针对awk 范围的信息时,您的答案才是好的。我的目的是显示有关 shell 的一般使用信息。如果我将usage() 放入awk,我将不得不调用awk 才能在usage() 之外调用awk
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-07-18
      • 2022-01-08
      • 2022-09-27
      • 1970-01-01
      • 2014-08-21
      • 2014-11-24
      相关资源
      最近更新 更多