简体   繁体   English

awk:在awk之外调用一个函数

[英]awk: calling a function outside of awk

Update: 更新:

I'm working on a modular shell script which calls usage() in different level of subprocess. 我正在研究一个模块化的shell脚本,它在不同级别的子进程中调用usage() The script sample.sh has the structure resembles below: 脚本sample.sh的结构类似于:

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

usage() displays brief information on how to use the script (eg available arguments and its descriptions). usage()显示有关如何使用脚本的简要信息(例如,可用参数及其描述)。 When executed for the first time, usage() is displayed in the beginning of the script. 第一次执行时, usage()显示在脚本的开头。 Examples of other conditions for usage() invocation include: usage()调用的其他条件示例包括:

  1. awk fails to validate input from stdio or files awk无法验证stdio或文件的输入

  2. argument --help is received 参数--help被收到了

  3. other user-derived failures are occurred 发生其他用户派生的故障

I'd like to call identical function, usage() , from shell and its direct child process, awk . 我想从shell及其直接子进程awk调用相同的函数usage()


Original Question: 原始问题:

Function, usage() of sample.sh prints its print statement as desired. sample.sh函数, usage()根据需要打印其print语句。

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

To take out usage() from awk and put it as a local function in sample.sh~ , I tried: 要从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

As we observe, we get the error message saying "undefined function usage" in sample.sh~ . 正如我们所观察到的,我们在sample.sh~收到错误消息“未定义的函数用法”。 How should I improve it? 我该怎样改进它?

I find a way to call function out of awk 我找到了一种从awk调用函数的方法

put below code in a file, such as call it a.sh 将下面的代码放在一个文件中,例如将其命名为a.sh

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

$ chmod +x a.sh

then you can call the function in awk 然后你可以在awk中调用该函数

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

A child process cannot call a function in the parent, and vice versa. 子进程无法调用父进程中的函数,反之亦然。 Not even in the same language. 甚至不是同一种语言。

What you can do, is start another instance of the shell script that contains your awk script. 你可以做的是启动包含你的awk脚本的shell脚本的另一个实例。 For example, save this in a script called ./script.sh : 例如,将其保存在名为./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()
}'

Make it executable, and run as ./script.sh . 使其可执行,并以./script.sh身份运行。 In this script, the usage function inside the inner awk script simply re-runs the containing shell script with the --usage script. 在此脚本中,内部awk脚本中的usage函数只需使用--usage脚本重新运行包含的shell脚本。 Keep in mind that there will be 3 processes here: shell -> awk -> shell. 请记住,这里将有3个进程:shell - > awk - > shell。 It's not possible to do this in a single process. 在一个过程中无法做到这一点。

Original answer 原始答案

If you move the usage function definition outside of awk , then it's normal that you cannot execute from inside. 如果将usage函数定义移到awk之外,则无法从内部执行是正常的。 If you want to execute awk commands you have to be inside of an awk interpreter, and can only use what is defined inside. 如果要执行awk命令,则必须在awk解释器中,并且只能使用内部定义的内容。

Note sure if this is what you're looking for, but you can move the function definition to another awk file and have awk process it, for example: 请注意,如果这是您正在寻找的,但您可以将函数定义移动到另一个awk文件并让awk处理它,例如:

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

With bash , another option is to export shell functions with export -f , which then become available to awk via the system() call: 使用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") 
  }'

Note that awk invokes sh with system() , which may or may not be bash - if it IS bash (eg, on OSX), you don't strictly need the /usr/bin/env bash -c portion, but leaving it in should make it work on most platforms (that have bash). 注意, awk使用system()调用sh ,这可能是也可能不是bash - 如果它是bash (例如,在OSX上),你不需要/usr/bin/env bash -c部分,但是保留它应该使它适用于大多数平台(有bash)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM