
Я пытаюсь пройтипеременнаяколичество аргументов из скрипта оболочки в подмножество распознавания образов таблицы. Вот моя попытка на данный момент:
Файл «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, не требующего многократной обработки входного файла.