将参数传递给awk里面的do循环

时间:2016-07-07 23:06:59

标签: linux bash shell awk

我有大量以制表符分隔的文本文件,其中包含我在第二栏中感兴趣的分数:

test_score_1.txt

Title   FRED Chemgauss4 File
24937   -6.111582   A
24972   -7.644171   A
26246   -8.551361   A
21453   -7.291059   A

test_score_2.txt

Title   FRED Chemgauss4 File
14721   -7.322331   B
27280   -6.229842   B
21451   -8.407396   B
10035   -7.482369   B
10037   -7.706176   B

我想检查一下得分小于我定义的数字的标题。

以下代码在脚本中定义我的分数并且有效:

check_score_1

#!/bin/bash

find . -name 'test_score_*.txt' -type f -print0 |
while read -r -d $'\0' x; do
    awk '{FS = "\t" ; if ($2 < -7.5) print $0}' "$x"
done

如果我尝试将参数传递给awk,如check_scores_2.sh "-7.5" check_score_2.sh所示,那将返回两个文件中的所有条目。

check_scores_2.sh

#!/bin/bash

find . -name 'test_score_*.txt' -type f -print0 |
while read -r -d $'\0' x; do
    awk '{FS = "\t" ; if ($2 < ARGV[1]) print $0}' "$x"
done

最后,check_scores_3.sh显示我实际上没有从命令行传递任何参数。

check_scores_3.sh

#!/bin/bash

find . -name 'test_score_*.txt' -type f -print0 |
while read -r -d $'\0' x; do
    awk '{print ARGV[0] "\t" ARGV[1] "\t" ARGV[2]}' "$x"
done

$ ./check_score_3.sh "-7.5"给出以下输出:

awk ./test_score_1.txt  
awk ./test_score_1.txt  
awk ./test_score_1.txt  
awk ./test_score_1.txt  
awk ./test_score_1.txt  
awk ./test_score_2.txt  
awk ./test_score_2.txt  
awk ./test_score_2.txt  
awk ./test_score_2.txt  
awk ./test_score_2.txt  
awk ./test_score_2.txt  

我做错了什么?

2 个答案:

答案 0 :(得分:3)

在shell脚本中,shellscript的第一个参数以$1形式提供。您可以将该值分配给awk变量,如下所示:

find . -name 'test_score_*.txt' -type f -exec awk -v a="$1" -F'\t' '$2 < a' {} +

讨论

  • 你的print0 / while读取循环非常好。但是,-exec提供的find选项可以在没有任何显式循环的情况下运行相同的命令。

  • 可以选择将命令{if ($2 < -7.5) print $0}简化为条件$2 < -7.5。这是因为条件的默认操作是print $0

  • 请注意,引用$1$2完全无关。因为$1是双引号,所以在 awk命令开始运行之前,shell会替换它。 shell将$1解释为脚本的第一个参数。因为$2出现在单引号中,所以shell将其单独保留,并由awk解释。 Awk将其解释为其当前记录的第二个字段。

答案 1 :(得分:0)

你的第一个例子:

awk '{FS = "\t" ; if ($2 < -7.5) print $0}' "$x"
只有设置FS实际上对你的特定情况没有任何影响的巧合才能实现。否则它将对输入文件的第一行失败,因为你没有设置FS直到读取第一行之后并且已经拆分成字段。你的意思是:

awk 'BEGIN{FS = "\t"} {if ($2 < -7.5) print $0}' "$x"

可以更恰当地写成:

awk -F'\t' '$2 < -7.5' "$x"

对于第二种情况,你只是没有传递参数,正如你已经意识到的那样。您所需要做的就是:

awk -F'\t' -v max="$1" '$2 < max' "$x"

请参阅http://cfajohnson.com/shell/cus-faq-2.html#Q24