AWK内でbashシェル関数を使用する


24

AWK内でbash関数を何らかの形で使用することは可能ですか?

サンプルファイル(string、int、int、int)

Mike 247808 247809 247810

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

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

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

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

回答:


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またはシェルスクリプトで定義された関数」では機能しません。
マイケルホーマー14

@MichaelHomerはい、あなたは正しいです。あなたのコメントのおかげで、私は誰も尋ねなかった質問に答えたことに気付きました。しかし、現在のスクリプト(および場合によっては他のスクリプトからsource)の関数を使用する方法を見つけましたが、なぜ機能しないのかはわかりません.bashrc
アカリリマノ14

2
内容が$2シェルコードとして解釈されるため、コマンドインジェクションの脆弱性でもあります。
ステファンシャゼル

8

awkからbashを呼び出して、その出力を使用できます。頻繁に発生する場合、パフォーマンスの観点からは明らかに危険です。マニュアルページを引用する:

command | getline [var]

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

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


ハウケ・レイジング、とてもクール!
-JJoao

これを何度も使用しましたが、うまく機能します。
デイブリックス

4

これを試してみてください:

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

知る限り、awkではbash関数を使用できず、スクリプトのみを使用できます。必要に応じてawk関数を使用できます。


3

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

私はクイーンズを代表し、彼女はブルックリンで育った
ブルーノ・ブロノスキー

3

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

些細ではありません。

bashそれはの後続の呼び出しに利用できるような機能をエクスポートするサポートbashようにする関数の定義を渡すための一つの方法だ、bashによって呼び出さawk

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))}'

これは、各行shで1つずつ実行することを意味する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

ちょっとしたハックで@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.
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.