我有大量以制表符分隔的文本文件,其中包含我在第二列中感兴趣的分数:
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

我究竟做错了什么?

最佳答案

在您的 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 是双引号,所以 shell 会在 awk 命令开始运行之前替换它。 shell 将 $1 解释为脚本的第一个参数。因为 $2 出现在单引号中,所以 shell 不理会它,它由 awk 解释。 Awk 将其解释为表示其当前记录的第二个字段。
  • 关于linux - 在 do 循环中将参数传递给 awk,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/38256635/

    10-16 21:43