Використання функції bash shell всередині AWK


24

Чи можна якось використовувати функцію bash всередині 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. Але ви все одно можете використовувати функції з вашого поточного сценарію 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

EDIT 2:

Я не знаю чому, але це не працює на моєму Ubuntu 16.04. Це дивно, адже він працював на Ubuntu 14.04.


Це могло б працювати, якби d2hбуло виконуваним файлом, але не, якщо це "функція, визначена або в .bashrc або в скрипті оболонки".
Майкл Гомер

@MichaelHomer так, ви праві. Завдяки вашому коментарю я зрозумів, що відповів на питання, яке ніхто не задавав. Але я знайшов спосіб використовувати функції з поточного сценарію (а можливо, і з інших сценаріїв через source), але не можу зрозуміти, чому це не працює .bashrc.
акарілімано

2
Це також вразливість введення команд, оскільки вміст в $2кінцевому підсумку трактується як код оболонки.
Стефан Шазелас

8

Ви можете викликати bash з awk і використовувати його вихід. Це очевидно небезпечно з точки зору продуктивності, якщо це трапляється занадто часто. Цитуючи сторінку чоловіка:

command | getline [var]

Запустіть команду, переносячи вихід, або в $ 0, або в var,

Команда буде bash-скриптом, який містить визначення функції та виконує функцію.


Hauke ​​Laging, дуже круто!
JJoao

Я використовував це багато разів, і це добре працює.
Дейв Рікс

4

Спробуйте зробити це:

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

AFAIK, ви не можете використовувати функцію bash в awk, а лише сценарій. При необхідності можна використовувати функцію awk.


3

Використання визначеної користувачем функції bash всередині awk

Відмова: Я розумію, що це не те, що намагається зробити ОП, але 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.
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.