AWK: Передача переменных оболочки в awk

AWK: Передача переменных оболочки в awk

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

Файл «infile»:

    ID,GROUP
    1,GROUP2    
    2,GROUP2    
    3,GROUP4    
    4,GROUP4    
    5,GROUP5    
    6,GROUP5    
    7,GROUP23   
    8,GROUP23   
    9,GROUP23   

Файл subset.sh:

    #!/bin/sh
    rm -f outfile_$week

    week = $1
    shift

    for TOKEN in "$@"
    do

    echo "adding records for" $TOKEN

    awk -F "," -v group = $TOKEN '{ if(FNR > 2 && $2 ~/group/){print $0} }' infile >> outfile_$week
    done

Я также пробовал group = "$TOKEN", "group = $TOKEN" и затем оба с одинарными кавычками. Я отправляю так:

    sh subset.sh 061314 GROUP2 GROUP23

Ошибка, которую я получаю, поразительно неинформативна.

    Usage: awk [-F fs][-v Assignment][-f Progfile|Program][Assignment|File] ...

Любая помощь будет оценена по достоинству, спасибо!

EDIT: Я попробовал бежать

    awk -F "," -v group ="GROUP1" '{ if(FNR > 2 && $2 ~/group/){print $0} }' infile

безрезультатно... (та же ошибка, что и выше) кто-нибудь знает причину, по которой это может произойти?

решение1

Вам следует написать:

-v group="$TOKEN"

вместо -v group = $TOKEN, что приводит к синтаксической ошибке в awk.

решение2

Похоже, вы хотите:

awk -F, '
  BEGIN {
    for (i = 1; i < ARGC; i++) group[ARGV[i]]
    ARGC=0
  }
  NR >= 2 && $2 in group' "$@" < infile

Или, если вы действительно хотите рассматривать аргументы как регулярные выражения для сопоставления со вторым столбцом:

awk -F, '
  BEGIN {
    for (i = 1; i < ARGC; i++) group[ARGV[i]]
    ARGC=0
  }
  NR >= 2 {
    for (i in group) if ($2 ~ i) {print; next}
  }' "$@" < infile

решение3

Ваша непосредственная проблема — пробелы вокруг знака равенства. Аргументом опции -vдолжно быть присваивание. Awk видит аргумент -v, за которым следует скрипт ( =), за которым следуют имена файлов (значение TOKEN, ваш скрипт и имена ваших файлов).

Вы допустили аналогичную ошибку в скрипте оболочки выше: week = $1должно быть week="$1".

Кстати,всегда заключайте подстановки команд в двойные кавычки. Например, если TOKENэто *, он будет заменен списком файлов в текущем каталоге.

awk -v "group=$TOKEN"

Однако это не устанавливает groupзначение TOKEN, поскольку awk рассматривает правую часть присваивания как литерал в синтаксисе awk. Например, если значение TOKEN— это 7-символьная строка foo\bar, то переменная awk groupустанавливается в 6-символьную строку, foo␈arгде — символ возврата на одну позицию (байтовое значение 8).

Самый простой способ передать переменную в скрипт awk — экспортировать ее в среду и использовать через массив ENVIRON.

Кроме того, вы не используете переменную groupнигде в скрипте awk. Регулярное выражение /group/соответствует любой строке, содержащей 5-символьную строку group. Если вы хотите проверить, является ли поле точным значением group(например, если значение TOKENравно GROUP2, то поле, содержащее , GROUP24не будет соответствовать), используйте оператор равенства ==.

  export TOKEN
  awk -F "," '{ if (FNR > 2 && $2 == ENVIRON["TOKEN"]){print $0} }' infile >> outfile_$week

Вот весь скрипт, немного упрощенный для использования синтаксиса условия-действия awk (где действие здесь опущено, поскольку оно используется print $0по умолчанию) и для того, чтобы не открывать выходной файл каждый раз:

#!/bin/sh
week="$1"
shift
for TOKEN in "$@"
do
  echo "adding records for" $TOKEN
  awk -F "," 'FNR > 2 && $2 == ENVIRON["TOKEN"]' infile 
done >"outfile_$week"

ВидетьОтвет Стефана Шазеласадля более продвинутого способа использования awk, не требующего многократной обработки входного файла.

Связанный контент