在AWK中使用bash shell函数


24

是否可以以某种方式在AWK中使用bash函数?

示例文件(字符串,整数,整数,整数)

Mike 247808 247809 247810

尝试将值从十进制转换为十六进制。

在.bashrc或Shell脚本中定义的函数。

awk '{print $1 ; d2h($2)}' file

awk:调用未定义函数d2h输入记录号1,文件文件源行号1

Answers:


27

尝试使用system()功能:

awk '{printf("%s ",$1); system("d2h " $2)}' file

在您的情况下,system将调用d2h 247808此命令的printf输出,然后将其追加到输出:

Mike 3C800

编辑:

作为system使用sh而不是bash我找不到访问的方法.bashrc。但是您仍然可以使用当前bash脚本中的函数:

#!/bin/bash
d2h() {
    # do some cool conversion here
    echo "$1" # or just output the first parameter
}
export -f d2h
awk '{printf("%s ",$1); system("bash -c '\''d2h "$2"'\''")}' file

编辑2:

我不知道为什么,但这在我的Ubuntu 16.04上不起作用。这很奇怪,因为它曾经在Ubuntu 14.04上工作。


d2h如果它是可执行文件,则可以工作,但如果它是“在.bashrc或Shell脚本中定义的函数”,则不行。
Michael Homer 2014年

@MichaelHomer是的,您是对的。感谢您的评论,我意识到我已经回答了没人问的问题。但是我已经找到了一种使用当前脚本中的函数的方法(可能还可以通过来使用其他脚本中的函数source),但是我无法弄清楚为什么它不能用于.bashrc
akarilimano 2014年

2
这也是一个命令注入漏洞,因为最终的内容$2最终被解释为shell代码。
斯特凡Chazelas

8

您可以从awk调用bash并使用其输出。从性能的角度来看,如果这种情况发生得太频繁,那显然是危险的。引用手册页:

command | getline [var]

运行命令,将输出传递到$ 0或var中,

command将是一个bash脚本,其中包含函数定义并执行该函数。


Hauke Laging,非常酷!
JJoao

我已经使用了很多次,并且效果很好。
戴夫·里克斯

4

尝试这样做:

awk '{print $1 ; printf "%x\n", $2}' file

AFAIK,您不能在awk中使用bash函数,而只能使用脚本。如果需要,可以使用awk函数。


3

在awk中使用用户定义的bash函数

免责声明:我知道这不是OP想要做的,但是Google会带领其他人像我一样得到这个答案。

情况

您有一个bash按功能组织的脚本(因为您不讨厌自己或[大多数]同事),并且这些功能中至少有一个需要从内部调用另一个awk

脚本

#!/bin/env bash

# The main function - it's a sound pattern even in BASH
main(){
    # In the awk command I do some tricky things with single quotes. Count carefully...
    # The first $0 is outside the single quotes so it is the name of the current bash script.
    # The second $0 is inside the single quotes so it is awk's current line of input.
    awk '{printf("%s. ", ++c); system("'$0' --do"); print $0}'<<-PRETEND_THIS_IS_AN_INPUT_STREAM
        and
        and
        well
    PRETEND_THIS_IS_AN_INPUT_STREAM
}

# functionized to keep things DRY
doit(){
    echo -n "doin' it "
}


# check for a command switch and call different functionality if it is found
if [[ $# -eq 1 && $1 == "--do" ]];
then
        doit
else
        main
fi

输出量

$ ./example.sh
1. doin' it and
2. doin' it and
3. doin' it well

我代表皇后区,她在布鲁克林长大
Bruno Bronosky

3

awk可以运行awk功能。要使其运行bash功能,您需要awk执行一个bashshell,bash以解释该函数的定义并调用该函数,并使用awk传递的值作为参数来提取该函数。

不平凡。

bash支持导出函数,因此可以在后续的中调用bash,因此这是将函数的定义传递给bashby的方法之一awk

export -f d2h

awk执行命令(bash此处)的唯一方法是使用system("cmd")print... | "cmd""cmd" | getline。在所有情况下,都awk运行一个shell来解释它cmd,但是它将是shnot bash。因此,您需要为此构造一个命令行,shbash调用是对bash命令行的解释,以调用该函数,因此在引用时必须小心:

export -f d2h
<file awk -v q="'" '
  function shquote(s) {
    gsub(q, q "\\" q q, s)
    return q s q
  }
  {print $1; system("bash -c '\''d2h \"$1\"'\'' bash " shquote($2))}'

这确实意味着要为每条线运行一个sh和一个bash,因此效率将非常低下。与使用以下命令bash进行读取和拆分相比,这最终将导致效率大大降低while read loop

(unset IFS; while read -r a b rest; do
  printf '%s\n' "$a"
  d2h "$b"
 done < file)

0

这会给你很好的机会。

cat ../logs/em2.log.1 |grep -i 192.168.21.15 |awk '{system("date"); print $1}'

系统功能使您可以解析awk流中的bash命令。


0

只是快速的hack演示了@HaukeLaging command|getline

1)让输入为:

Dear friends
my name is `id -nu` and
today is `date "+%Y-%m-%d"`.

按照shell语法,在输入中,

`command`

用于表示将被执行结果替换的内联命令

2)我们可以通过以下方式扩展内联shell命令:

#!/usr/bin/gawk -f

BEGIN  { FS ="`";        }
NF==3  { $2 | getline $2 }
       { print           }

3)用法(在通常的chmod之后):

$ expand-inline input
Dear friends
my name is jjoao and
today is 2018-01-15.
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.