AWK içinde bash shell işlevini kullanma


24

Bir şekilde AWK içinde bash işlevini kullanmak mümkün mü?

Örnek dosya (string, int, int, int)

Mike 247808 247809 247810

Değerleri ondalık sayıdan onaltılık alana dönüştürmeye çalışıyorum.

İşlev ya .bashrc ya da kabuk betiğinde tanımlanmıştır.

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

awk: tanımsız işlev d2h giriş kayıt numarası 1, dosya dosyası kaynak satır numarası 1'i çağırmak

Yanıtlar:


27

system()Fonksiyonu kullanmaya çalışın :

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

Senin durumunda systemarayacak d2h 247808ve sonra bu komutun çıktısını çıktıya ekleyecektir printf:

Mike 3C800

DÜZENLE:

Gibi systemkullanımlar shyerine bashI erişmek için bir yol bulamıyorum .bashrc. Ancak hala mevcut bash betiğinizden fonksiyonlarını kullanabilirsiniz:

#!/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

EDIT 2:

Nedenini bilmiyorum, ama bu Ubuntu 16.04'ümde çalışmıyor. Bu garip, çünkü Ubuntu 14.04 üzerinde çalışıyordu.


Bu, d2hçalıştırılabilir olsa da işe yarayabilir , ancak "ya .bashrc'de ya da kabuk komut dosyasında tanımlanmış bir işlev" değilse işe yaramadı .
Michael Homer,

@MichaelHomer evet, haklısın. Yorumunuz sayesinde kimsenin sormadığı soruyu cevapladığımı fark ettim. Fakat fonksiyonları mevcut komut dosyasından (ve muhtemelen diğer komut dosyalarından sourceyazarak) kullanmanın bir yolunu buldum, ancak bunun neden işe yaramadığını anlayamadım .bashrc.
akarilimano

2
Bu ayrıca, içeriğin $2kabuk kodu olarak yorumlanmasıyla sonuçlanan bir komut enjeksiyon güvenlik açığıdır .
Stéphane Chazelas

8

Bash'ı awk'den çağırabilir ve çıktısını kullanabilirsiniz. Çok sık meydana gelirse bu açıkça performans açısından tehlikelidir. Man sayfasından alıntı:

command | getline [var]

Komutu çıkışı $ 0 veya var olarak çalıştırın,

komut, işlev tanımını içeren ve işlevi yürüten bir bash komut dosyası olacaktır.


Hauke ​​Laging, çok havalı!
JJoao,

Bunu birçok kez kullandım ve iyi çalışıyor.
Dave Rix

4

Bunu yapmayı deneyin:

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

AFAIK, bir bash fonksiyonunu awk olarak kullanamazsınız, sadece betiği kullanırsınız. Gerekirse bir awk işlevini kullanabilirsiniz.


3

Awk içinde kullanıcı tanımlı bash işlevini kullanma

Feragatname: OP'nin yapmaya çalıştığı şeyin bu olmadığını biliyorum, ancak Google benim gibi diğerlerini bu cevaba yönlendirecektir.

Durum

bashİşlevlerle düzenlenmiş bir komut dosyasına sahipsiniz (çünkü kendinizden veya [çoğu] çalışanlarınızdan nefret etmediğiniz için) ve bu işlevlerden en az birinin içinden başka birisini çağırması gerekir awk.

Çözüm

Senaryo

#!/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

Çıktı

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

Queens'i temsil ediyorum, Brooklyn'de büyüdü
Bruno Bronosky

3

awkawkfonksiyonları çalıştırabilir . O çalışması için bashfonksiyonlar, Size gereken tek şey awkbir yürütme basholduğunu, kabuk bashtarafından çıkarılan değerle, bu işlevin tanımını yorumlamak ve bu işlevi çağırmak awkargüman olarak geçti.

Önemsiz değil.

bashdışa aktarma işlevlerini destekler bash, böylece sonraki çağrılarında kullanılabilir , bu nedenle işlev tanımını bashçağrılan kişiye iletmenin bir yolu awk:

export -f d2h

awkBir komutu ( bashburada) yürütmenin tek yolu system("cmd"), veya print... | "cmd"veya iledir "cmd" | getline. Her durumda, awkbunu yorumlamak için bir kabuk çalıştırır cmd, ancak sholmayacak bash. Bunun için bir komut satırı oluşturmalısınız sh, bunun için işlevi çağırmak için bashbir bashkomut satırını yorumlayan bir çağrıdır , bu yüzden alıntı yapmak için dikkatli olmanız gerekir:

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

Bu, her bir hat için bir shve bir kez koşmak anlamına gelir bash, bu yüzden oldukça verimsiz olacaktır. Bu bash, okuma yapmaktan ve a ile bölmekten çok daha fazla verimsiz olmakla sonuçlanır while read loop:

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

0

Bu size iyi şanslar verecektir.

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

sistem işlevi, awk akışı içindeki bash komutunu ayrıştırmanıza olanak sağlar.


0

Sadece hızlı bir kesmek @HaukeLaging'i gösteriyor command|getline :

1) giriş olsun:

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

Kabuk sözdiziminin ardından, girişte,

`command`

onun yerine getirilmesiyle değiştirilecek satır içi komutları belirtmek için kullanılır .

2) Satır içi kabuk komutunu şu şekilde genişletebiliriz:

#!/usr/bin/gawk -f

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

3) Kullanım (normal chmod'dan sonra):

$ expand-inline input
Dear friends
my name is jjoao and
today is 2018-01-15.
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.