我正在尝试使用 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。
答案1
您应该使用-v
以下选项awk
:
awk -F',' -v accNum="$1" '$1 == accNum {print $3,$2}'
使用$1
双引号时,shell 将为您处理所有其特殊字符(如果有)。
答案2
你有:
accountNum=$1
awk -F',' '{ if($1==accountNum) { print $3.$2 } }' Accounts
shell变量是如何accountNum
进入的awk
?事实并非如此:您需要awk
明确提供其值。您可以使用:
awk -F',' '{ if($1=='"$accountNum"') { print $3.$2 } }' Accounts
它留下单引号并让 shell 将其变量的值替换到命令中awk
,然后为命令字符串的其余部分重新输入单引号。
更好或至少更惯用的脚本是:
#!/bin/sh
accountNum=$1
awk -F, '$1 == "'"$accountNum"'" { print $3,$2 }' Accounts
它处理非数字帐号(引用替换的变量),使用模式块而不是显式块if
({}
如果之前的测试为真,则该块将运行),并根据需要打印名称之间的空格(因为,
)。如果您更喜欢显式使用if
,请将测试移至现有if
语句内。
根据您的真实目标,awk
可能并不最适合您正在做的事情。如果脚本$1
中有引号,上面的方法仍然会失败。尽管您的 shell 循环会多次重复输出,但它没有做任何有用的事情。
答案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
每行单独的进程。我想,仅供参考。
答案4
#!/bin/bash
awk -v a="$1" -F ',' '$1 == a { print $3, $2 }' Accounts
我们将变量-v a="$1"
设置为脚本第一个命令行参数的值,然后指定输入以逗号分隔。如果第一列等于 的值,则按相反顺序打印其他两列。awk
a
-F ','
a
awk
当您将第一列与未设置的变量进行比较时,您在输出中什么也得不到accountNum
。
如果某个条目的第一列包含 0(零),则该条目将被打印。这是因为未设置变量的值awk
计算为零。