web-dev-qa-db-ja.com

AWK内でのbashシェル関数の使用

どういうわけかAWK内でbash関数を使用することは可能ですか?

ファイルの例(string、int、int、int)

Mike 247808 247809 247810

値を10進数から16進数に変換しようとしています。

.bashrcまたはシェルスクリプトで定義された関数。

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

awk:未定義の関数d2h入力レコード番号1、ファイルファイルソース行番号1を呼び出しています

27
tiny

system()関数を使用してみてください:

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

あなたの場合、systemd2h 247808を呼び出し、次にこのコマンドの出力をprintf出力に追加します。

Mike 3C800

編集:

systemshではなく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で機能していたため、奇妙です。

31
akarilimano

Awkからbashを呼び出して、その出力を使用できます。それが頻繁に発生すると、パフォーマンスの観点から明らかに危険です。 manページを引用する:

command | getline [var]

$ 0またはvarに出力をパイプするコマンドを実行します。

コマンドは、関数定義を含み、関数を実行するbashスクリプトです。

9
Hauke Laging

awkawk関数を実行できます。 bash関数を実行するには、awkシェルを実行するためにbashが、その関数の定義を解釈するためにbashが必要であり、 awkによって抽出された値を引数として渡した関数。

ささいなことではありません。

bashは関数のエクスポートをサポートしているため、その後のbashの呼び出しで使用できます。これは、bashによって呼び出されたawkに関数の定義を渡す1つの方法です。 :

_export -f d2h
_

awkがコマンドを実行する唯一の方法(ここではbash)は、そのsystem("cmd")、または_print... | "cmd"_または_"cmd" | getline_を使用する方法です。すべての場合において、awkはシェルを実行してそのcmdを解釈しますが、shではなくbashになります。したがって、関数を呼び出すためにshコマンドラインを解釈するbash呼び出しである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))}'
_

これは、各行に1つのshと1つのbashを実行することを意味するため、非常に非効率になります。その場合、bashに_while read loop_を使用して読み取りと分割を行わせるよりも、はるかに非効率的になります。

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

これを試してください:

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

AFAIK、あなたはawkでbash関数を使うことはできませんが、スクリプトだけを使うことができます。必要に応じてawk関数を使用できます。

5
Gilles Quenot

Awk内でユーザー定義のbash関数を使用する

免責事項:これはOPが試みていることではないことを理解していますが、Googleは私のような他の人をこの答えに導きます。

状況

関数で構成されたbashスクリプトがあり(自分や[ほとんど]の同僚を憎んでいないため)、これらの関数の少なくとも1つが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
4
Bruno Bronosky

これはあなたに良いチャンスを与えるでしょう。

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

システム関数を使用すると、awkストリーム内のbashコマンドを解析できます。

1
Mansur Ali

@HaukeLagingを実証するための簡単なハックcommand|getline

1)入力を次のようにします。

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

シェル構文に従って、入力では、

`command`

インラインコマンドが彼の実行結果で置き換えられることを示すために使用されます。

2)インラインシェルコマンドを次のように展開できます。

#!/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.
1
JJoao