【问题标题】:Modify a shell variable inside awk block of code修改 awk 代码块中的 shell 变量
【发布时间】:2016-04-24 07:54:26
【问题描述】:

有没有办法修改 awk 代码块中的 shell 变量?

--------- [shell_awk.sh]---------------------
 #!/bin/bash

shell_variable_1=<value A>
shell_variable_2=<value B>
shell_variable_3=<value C>

awk 'function A(X)
{ return X+1 }
{ a=A('$shell_variable_1')
  b=A('$shell_variable_2')
  c=A('$shell_variable_3')
  shell_variable_1=a
  shell_variable_2=b
  shell_variable_3=c
}' FILE.TXT
--------- [shell_awk.sh]---------------------

这是一个非常简单的例子,真正的脚本加载一个文件并使用函数进行一些更改,我需要在更改为特定变量之前保留每个值,这样我就可以将前后值注册到MySQL中。

after 值是从参数($1、$2 等)接收的。

在我已经知道如何从文件中获取之前的值。

一切都做得很好,除了 shell_variable 由 awk 变量设置。 awk 块代码外面很容易设置,但是里面,可以吗?

【问题讨论】:

    标签: bash shell variables awk


    【解决方案1】:

    没有任何程序——在 awk、shell 或任何其他语言中——可以直接修改父进程的内存。这包括变量。但是,当然,您的 awk 可以将内容写入标准输出,而父 shell 可以读取该内容并自己修改自己的变量。


    这是一个 awk 的示例,它可以将键/值对写出以供 bash 读取。这并不完美——请阅读下面的注意事项。

    #!/bin/bash
    
    shell_variable_1=10
    shell_variable_2=20
    shell_variable_3=30
    
    run_awk() {
            awk -v shell_variable_1="$shell_variable_1" \
                -v shell_variable_2="$shell_variable_2" \
                -v shell_variable_3="$shell_variable_3" '
            function A(X) { return X+1 }
            { a=A(shell_variable_1)
              b=A(shell_variable_2)
              c=A(shell_variable_3) }
            END {
              print "shell_variable_1=" a
              print "shell_variable_2=" b
              print "shell_variable_3=" c
            }' <<<""
    }
    
    while IFS="=" read -r key value; do
            printf -v "$key" '%s' "$value"
    done < <(run_awk)
    
    for var in shell_variable_{1,2,3}; do
      printf 'New value for %s is %s\n' "$var" "${!var}"
    done
    

    优势

    • 不使用evalawk 的输出中的 $(rm -rf ~) 等内容不会被您的 shell 执行。

    缺点

    • 无法处理带有换行符的变量内容。 (您可以通过将 awk 脚​​本中的 NUL 分隔输出并将 -d '' 添加到 read 命令来解决此问题。
    • 恶意 awk 脚本可以修改 PATHLD_LIBRARY_PATH 或其他安全敏感变量。 (您可以通过将变量读入关联数组而不是全局命名空间来解决此问题,或者在它们的名称上添加前缀)。
    • 上面的代码使用了几个在 bash 中也可用的 ksh 扩展;但是,它不会与 POSIX sh 一起运行。因此,请确保不要通过 sh scriptname 运行此程序(这仅保证 POSIX 功能)。

    【讨论】:

    • 非常感谢您的回答,我会适应我的脚本并做一些测试,我会尽快返回结果
    • 你的脚本运行良好,是一个非常好的模型。不幸的是,我的脚本需要加载一个文件,并且按列位置(而不是分隔符位置),所以要做到这一点,我需要使用 read 通过 FD 打开文件,逐行读取,然后将它与 printf -v 一起使用您阅读的示例,所有这些都由功能分隔。我试着做一个简单的例子,但我失败了,我的最终脚本是受法律保护的,所以我只是没有代码解释。感谢您的帮助。
    • 您不应该需要这种解决方法:我将prints 放在END 语句中的全部原因是仅在您完成之后运行它们处理任何输入文件中的行。您确实在将 &lt;&lt;&lt;"" 替换为输入文件中的重定向时删除了它,对吧?
    • 顺便说一句,如果您最终要在每行输入中调用一次awk,我建议您最好在本机 bash 中实现您的处理。请参阅 mywiki.wooledge.org/BashFAQ/100 以开始使用某些操作,否则可能会首先查看 awk 了解。
    猜你喜欢
    • 2014-07-28
    • 1970-01-01
    • 2016-01-19
    • 2015-08-16
    • 1970-01-01
    • 1970-01-01
    • 2014-01-04
    • 2014-01-20
    • 1970-01-01
    相关资源
    最近更新 更多