Установка переменной среды BASH непосредственно в AWK (в однострочнике AWK) - PullRequest
1 голос
/ 24 июня 2010

У меня есть файл, который имеет два столбца значений с плавающей запятой. У меня также есть программа на C, которая принимает значение с плавающей запятой в качестве ввода и возвращает другое значение с плавающей запятой в качестве вывода.

Я хотел бы сделать следующее: для каждой строки в оригинале выполнить программу на C со значением в первом столбце в качестве входных данных, а затем распечатать первый столбец (без изменений), за которым следует второй столбец минус результат программы на C.

В качестве примера предположим, что c_program возвращает квадрат ввода и ведет себя так:

$ c_program 4
16
$

и предположим, что data_file выглядит следующим образом:

1 10
2 11
3 12
4 13

Что я хотел бы вернуть в качестве вывода, в данном случае, это

1 9
2 7
3 3
4 -3

Чтобы написать это в действительно схематичном псевдокоде, я хочу сделать что-то вроде этого:

awk '{print $ 1, $ 2 - `c_program $ 1`}' data_file

Но, конечно, я не могу просто передать $ 1, переменную awk, в вызов c_program. Как правильно это сделать, и желательно, как я могу это сделать, сохраняя при этом «awk one-liner»? (Я не хочу вытащить кувалду и написать для этого полноценную программу на C).

Ответы [ 5 ]

4 голосов
/ 24 июня 2010

вы просто делаете все в awk

awk '{cmd="c_program "$1; cmd|getline l;print $1,$2-l}' file
2 голосов
/ 24 июня 2010

Показывает, как выполнить команду в awk:

ls | awk '/^a/ {system("ls -ld " $1)}'

Вместо этого вы можете использовать bash-скрипт:

while read line
do 
    FIRST=`echo $line | cut -d' ' -f1`
    SECOND=`echo $line | cut -d' ' -f2`
    OUT=`expr $SECOND \* 4`
    echo $FIRST $OUT `expr $OUT - $SECOND`
done
1 голос
/ 24 июня 2010

Оболочка - лучший инструмент для этого, использующий немного использованную функцию. Существует переменная оболочки IFS, которая является разделителем полей ввода, который sh использует для разделения командных строк при разборе; по умолчанию <Space><Tab><Newline>, поэтому ls foo интерпретируется как два слова.

Когда set заданы аргументы , а не , начиная с -, он устанавливает позиционные параметры оболочки для содержимого аргументов, разделенных через IFS, таким образом:

#!/bin/sh
while read line ; do
    set $line
    subtrahend=`c_program $1`     
    echo $1 `expr $2 - $subtrahend`
done < data_file
0 голосов
/ 24 июня 2010

Как уже отмечали другие: awk недостаточно хорошо подготовлен для этой работы.Вот предложение в bash:

#!/bin/sh

data_file=$1

while read column_1 column_2 the_rest
do

    ((result=$(c_program $column_1)-$column_2))
    echo $column_1 $result "$the_rest"

done < $data_file

Сохраните это в файл, скажем myscript.sh, затем вызовите его как:

sh myscript.sh data_file

Команда чтения читает каждую строку из данныхфайл (который был перенаправлен на стандартный ввод) и назначьте первые 2 столбца переменным $ column_1 и $ column_2.Остальная часть строки, если таковая имеется, сохраняется в $ the_rest.

Далее я вычисляю результат на основе ваших требований и распечатываю строку на основе ваших требований.Обратите внимание, что я окружаю $ the_rest кавычками, чтобы зарезервировать интервал.Невыполнение этого приведет к тому, что во входном файле будет несколько сжатых пробелов в один.

0 голосов
/ 24 июня 2010

Pure Bash, без использования каких-либо внешних исполняемых файлов, кроме вашей программы:

#!/bin/bash
while read num1 num2
do
    (( result = $(c_program num2) - num1 ))
    echo "$num1 $result"
done
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...