awk с заявлениями if

8

Я пытаюсь распечатать из файла с помощью awk, но мой вывод пуст. Вот мой код до сих пор

accountNum=$1
while read -r LINE || [[ -n $LINE ]] ; do
            awk -F',' '{ if($1==accountNum) { print $3.$2 } }' Accounts
done < Accounts

Я также попробовал это:

accountNum=$1
while read -r LINE || [[ -n $LINE ]] ; do
            echo $LINE  | awk -F',' '{ if($1==accountNum) { print $3.$2 } }' 
done < Accounts

Входной файл:

1,Doe,John
2,Rooney,Wayne
3,Smith,Will
4,Crow,Russel
5,Cruise,Tom

Ожидаемый результат при запуске файла

$./file.sh 3
Will Smith

Но я получаю следующее

$./file.sh 3
$

Это ничего не печатается. Я знаю решение с разрезом, но я хочу использовать awk.

gkmohit
источник

Ответы:

8

Вы должны использовать -vопцию awk:

awk -F',' -v accNum="$1" '$1 == accNum {print $3,$2}'

В $1двойных кавычках оболочка будет обрабатывать все свои специальные символы (если есть) для вас.

cuonglm
источник
3

У тебя есть:

accountNum=$1
awk -F',' '{ if($1==accountNum) { print $3.$2 } }' Accounts

Как переменная оболочки accountNumпопасть awk? Это не так: вам нужно awkявно указать его значение . Ты можешь использовать:

awk -F',' '{ if($1=='"$accountNum"') { print $3.$2 } }' Accounts

который оставляет одинарные кавычки и оболочка подставляет значение своей переменной в awkкоманду, затем вводит одинарные кавычки для остальной части командной строки.

Лучшим или, по крайней мере, более идиоматическим сценарием будет:

#!/bin/sh
accountNum=$1
awk -F, '$1 == "'"$accountNum"'" { print $3,$2 }' Accounts

который имеет дело с нечисловыми номерами счетов (заключая в кавычки подставляемую переменную), использует блок шаблона вместо явного if( {}блок будет выполняться, если тест до того, как он станет истинным), и печатает пробел между именами, как вы хотели (из-за ,). Если вы предпочитаете использовать ifявно, переместите тест в существующий ifоператор.

В зависимости от вашей реальной цели, awkможет не подходить для того, что вы делаете. Выше все равно не работает, если в скрипте $1есть кавычки. Цикл оболочки, который у вас был, не делал ничего полезного, хотя он многократно повторял бы вывод.

Майкл Гомер
источник
ты говоришь, что я должен удалить whileпетлю? :)
gkmohit
По крайней мере, для примеров это не поможет вам.
Майкл Гомер
3

Ваш скрипт уже практически делает работу без каких-либо awk:

while IFS=, read -r num last first
    do  [ $((num==accountNum)) -eq 1 ] && 
        printf '%s.%s\n' "$first" "$last"
done < Accounts

Я не предполагаю, что это лучшее или более эффективное решение, чем использование в awkодиночку, но если вы хотите while...readцикл, это, безусловно, лучше, чем отдельные awkпроцессы для каждой строки. Я полагаю, просто к вашему сведению.

mikeserv
источник
Не только один awk для каждой строки, но этот awk снова читает весь файл для каждой строки, которую читает сама оболочка. Способ получить O (n ^ 2) алгоритм.
Paul_Pedant
1
#!/bin/bash

awk -v a="$1" -F ',' '$1 == a { print $3, $2 }' Accounts

При -v a="$1"установке awkпеременной aв значение первого аргумента командной строки скрипта, мы указываем, что ввод разделяется запятой -F ','. Если первый столбец равен значению a, выведите два других столбца в обратном порядке.

Вы ничего не получаете в своем выводе, когда сравниваете первый столбец с awkпеременной accountNum, которая не установлена.

Если бы была запись, в первом столбце которой было 0 (ноль), эта запись была бы напечатана. Это потому, что значение неустановленных переменных в awkнуле.

Кусалананда
источник