Sử dụng chức năng bash shell trong AWK


24

Có thể sử dụng chức năng bash trong AWK bằng cách nào đó?

Tệp ví dụ (chuỗi, int, int, int)

Mike 247808 247809 247810

Đang cố gắng chuyển đổi giá trị từ thập phân sang thập lục phân.

Hàm được định nghĩa trong .bashrc hoặc trong tập lệnh shell.

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

awk: gọi hàm không xác định d2h bản ghi đầu vào số 1, tệp dòng nguồn số 1

Câu trả lời:


27

Hãy thử sử dụng system()chức năng:

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

Trong trường hợp của bạn systemsẽ gọi d2h 247808và sau đó nối đầu ra của lệnh này với printfđầu ra:

Mike 3C800

CHỈNH SỬA:

Khi systemsử dụng shthay vì bashtôi không thể tìm cách truy cập .bashrc. Nhưng bạn vẫn có thể sử dụng các chức năng từ tập lệnh bash hiện tại của mình:

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

Tôi không biết tại sao, nhưng điều này không hoạt động trên Ubuntu 16.04 của tôi. Điều này thật lạ, vì nó từng hoạt động trên Ubuntu 14.04.


Điều này có thể hoạt động nếu d2hlà một tệp thực thi, nhưng không phải là "hàm được định nghĩa trong .bashrc hoặc trong tập lệnh shell".
Michael Homer

@MichaelHomer vâng, bạn nói đúng. Nhờ bình luận của bạn tôi nhận ra tôi đã trả lời câu hỏi không ai hỏi. Nhưng tôi đã tìm ra cách sử dụng các chức năng từ tập lệnh hiện tại (và có thể từ các tập lệnh khác thông qua source) nhưng tôi không thể hiểu tại sao nó không hoạt động .bashrc.
akarilimano

2
Đó cũng là một lỗ hổng tiêm lệnh vì nội dung $2cuối cùng được hiểu là mã shell.
Stéphane Chazelas

8

Bạn có thể gọi bash từ awk và sử dụng đầu ra của nó. Điều đó rõ ràng là nguy hiểm từ góc độ hiệu suất nếu nó xảy ra quá thường xuyên. Trích dẫn trang người đàn ông:

command | getline [var]

Chạy lệnh đường ống đầu ra hoặc thành $ 0 hoặc var,

lệnh sẽ là một tập lệnh bash chứa định nghĩa hàm và thực thi hàm.


Hauke ​​Laging, rất tuyệt!
JJoao

Tôi đã sử dụng điều này nhiều lần và nó hoạt động tốt.
Dave Rix

4

Hãy thử làm điều này:

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

AFAIK, bạn không thể sử dụng chức năng bash trong awk mà chỉ là tập lệnh. Bạn có thể sử dụng chức năng awk nếu cần.


3

Sử dụng hàm bash do người dùng định nghĩa bên trong awk

Tuyên bố miễn trừ trách nhiệm: Tôi nhận ra đây không phải là điều OP đang cố gắng thực hiện, nhưng Google sẽ dẫn những người khác như tôi đến câu trả lời này.

Tình hình

Bạn có một bashtập lệnh được tổ chức với các chức năng (vì bạn không ghét chính mình hoặc [hầu hết] đồng nghiệp) và ít nhất 1 trong số các chức năng đó cần phải gọi một chức năng khác từ bên trong awk.

Dung dịch

Kịch bản

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

Đầu ra

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

Tôi đại diện cho Queens, cô ấy đã lớn lên ở Brooklyn
Bruno Bronosky

3

awkCó thể chạy các awkchức năng. Để nó chạy các bashhàm, bạn cần awkthực thi một trình bashbao, bashđể diễn giải định nghĩa của hàm đó và gọi hàm đó, với giá trị được trích xuất bằng cách awkchuyển qua làm đối số.

Không tầm thường.

bashhỗ trợ xuất các hàm để nó có sẵn trong các lần gọi tiếp theo bash, vì vậy đó là một cách để chuyển định nghĩa của hàm sang lệnh bashđược gọi bởi awk:

export -f d2h

Các cách duy nhất awkđể thực thi một lệnh ( bashở đây) là bằng lệnh system("cmd")hoặc print... | "cmd"hoặc "cmd" | getline. Trong mọi trường hợp, awkchạy một cái vỏ để giải thích điều đó cmd, nhưng nó sẽ shkhông bash. Vì vậy, bạn cần xây dựng một dòng lệnh cho shđó là một bashlời gọi diễn giải một bashdòng lệnh để gọi hàm, vì vậy bạn cần cẩn thận với trích dẫn:

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

Điều đó không có nghĩa là chạy một shvà một bashcho mỗi dòng, do đó sẽ khá kém hiệu quả. Điều đó cuối cùng thậm chí còn kém hiệu quả hơn nhiều so với việc bashđọc và chia tách với while read loop:

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

0

Điều này sẽ cung cấp cho bạn cơ hội tốt.

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

chức năng hệ thống cho phép bạn phân tích lệnh bash trong luồng awk.


0

Chỉ cần một bản hack nhanh để chứng minh @HaukeLaging command|getline :

1) hãy để đầu vào là:

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

Theo cú pháp shell, trong đầu vào,

`command`

được sử dụng để biểu thị các lệnh nội tuyến được thay thế bằng kết quả thực hiện của mình.

2) Chúng tôi có thể mở rộng lệnh shell nội tuyến bằng cách:

#!/usr/bin/gawk -f

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

3) Cách sử dụng (sau chmod thông thường):

$ expand-inline input
Dear friends
my name is jjoao and
today is 2018-01-15.
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.