การใช้ฟังก์ชัน bash shell ภายใน AWK


24

เป็นไปได้ไหมที่จะใช้ฟังก์ชั่นทุบตีใน AWK?

ไฟล์ตัวอย่าง (สตริง, int, int, int)

Mike 247808 247809 247810

กำลังพยายามแปลงค่าจากฐานสิบเป็นฐานสิบหก

ฟังก์ชันกำหนดไว้ใน. 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ได้ แต่คุณยังสามารถใช้ฟังก์ชั่นได้จากสคริปต์ทุบตีปัจจุบันของคุณ:

#!/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 หรือในเชลล์สคริปต์"
Michael Homer

@MichaelHomer ใช่คุณพูดถูก ขอบคุณที่ความคิดเห็นของคุณฉันรู้ว่าฉันได้ตอบคำถามที่ไม่มีใครถาม แต่ฉันได้พบวิธีที่จะใช้ฟังก์ชั่นจากสคริปต์ปัจจุบัน (และอาจจะมาจากสคริปต์อื่น ๆ ผ่านทางsource) แต่ฉัน can'f .bashrcคิดออกว่าทำไมมันไม่ได้ทำงานร่วมกับ
akarilimano

2
นอกจากนี้ยังเป็นช่องโหว่ในการฉีดคำสั่งเนื่องจากเนื้อหาของการ$2สิ้นสุดถูกตีความว่าเป็นรหัสเชลล์
Stéphane Chazelas

8

คุณสามารถเรียก bash จาก awk และใช้เอาต์พุต เห็นได้ชัดว่าเป็นอันตรายจากมุมมองของประสิทธิภาพหากเกิดขึ้นบ่อยเกินไป การอ้างถึงหน้าคน:

command | getline [var]

รันคำสั่ง piping output ทั้ง $ 0 หรือ var

คำสั่งจะเป็นสคริปต์ทุบตีที่มีความหมายฟังก์ชั่นและดำเนินการฟังก์ชั่น


Hauke ​​Laging สุดยอดมาก!
JJoao

ฉันใช้มันมาหลายครั้งและใช้งานได้ดี
Dave Rix

4

ลองทำสิ่งนี้:

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

AFAIK คุณไม่สามารถใช้ฟังก์ชัน bash ใน awk ได้ แต่มีเพียงสคริปต์เท่านั้น คุณสามารถใช้ฟังก์ชั่น awk ได้ถ้าต้องการ


3

การใช้ฟังก์ชัน bash ที่ผู้ใช้กำหนดภายใน awk

ข้อจำกัดความรับผิดชอบ:ฉันรู้ว่านี่ไม่ใช่สิ่งที่ 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

awkสามารถเรียกใช้awkฟังก์ชั่น เพื่อให้เรียกใช้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และหนึ่ง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}'

ฟังก์ชั่นระบบช่วยให้คุณสามารถแยกวิเคราะห์คำสั่ง bash ภายในสตรีม awk


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.