用if语句awk


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
$

那什么都没有打印出来。我知道cut的解决方案,但我想使用awk。

Answers:


8

您应该使用以下-v选项awk

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

$1双引号括起来,shell将为您处理其所有特殊字符(如果有)。


3

你有:

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

shell变量如何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带有引号,则上述操作仍然失败。您执行的Shell循环没有做任何有用的事情,尽管它会重复输出多次。


您是说我应该删除while循环吗?:)
gkmohit14年

至少对于示例来说,它没有任何帮助。
Michael Homer 2014年

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每行都需要单独的流程。我想仅供参考。


不仅每行一个awk,而且该awk再次读取shell本身读取的每一行的整个文件。获得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(零),则该条目将被打印出来。这是因为in中未设置的变量的awk值等于零。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.