使用 AWK 从大量数字列表中获取特定范围的数值

Fetching a specific range of numeric value from huge list of numbers using AWK

我想取出特定范围的巨大数值,720000002774991000 到 720000002774991099。所以我尝试了以下命令,

awk -F, ' { if (( >= 720000002774991000) && ( <= 720000002774991099)) print [=10=]} ' VOUCHER_DUMP_REPORT.csv | head

VOUCHER_DUMP_REPORT.csv 是我的输入文件,只有一列这么大的数字。

但是我得到的输出不准确,它有一些不同于我给出的范围的值。

输出:

720000002774991065
720000002774991082
720000002774990985
720000002774991131
720000002774990919
720000002774991110
720000002774990947
720000002774991070
720000002774991042
720000002774991044

您的数字似乎太长,无法正确表示为整数。

您有几个可能的解决方案。使用 GNU awk,您可以使用 -M 启用对 arbitrary precision integers:

的支持
awk -M ' >= 720000002774991000 &&  <= 720000002774991099' file

否则,如果您确定第一列仅包含数字,则可以使用字符串比较:

awk -F, -v min=720000002774991000 -v max=720000002774991099 '
  BEGIN { lmin = length(min); lmax = length(max) } # save length of min and max
  ""  < min || ""  > max { next }            # skip lines which fail string comparison
  { l1 = length() }                            # calculate length of field
  l1 >= lmin && l1 <= lmax                       # check that string length is correct
' file

"" 将空字符串与第一个字段的内容连接起来,这会强制 awk 将其视为字符串而不是数字。如果没有这个,比较将是数字的,而不是词汇的,并且您将遇到与最初尝试相同的问题。

一个可能效率较低但可能更容易理解的使用字符串比较的版本是:

awk -F, -v min=720000002774991000 -v max=720000002774991099 '
  ""  >= min && ""  <= max \
  && length() >= length(min) && length() <= length(max)' file

和之前的版本一样,打印通过字符串比较和长度比较的行。这种方法的缺点是 minmax</code> 的长度计算次数超过了必要的次数。</p> <hr> <h3>测试(以上三种方法)</h3> <pre><code>$ cat file 720000002774991065 720000002774991082 720000002774990985 720000002774991131 720000002774990919 720000002774991110 720000002774990947 720000002774991070 720000002774991042 720000002774991044 $ awk -M ' >= 720000002774991000 && <= 720000002774991099' file 720000002774991065 720000002774991082 720000002774991070 720000002774991042 720000002774991044 $ awk -F, -v min=720000002774991000 -v max=720000002774991099 ' BEGIN { lmin = length(min); lmax = length(max) } # save length of min and max "" < min || "" > max { next } # skip lines which fail string comparison { l1 = length() } # calculate length of field l1 >= lmin && l1 <= lmax # check that string length is correct ' file 720000002774991065 720000002774991082 720000002774991070 720000002774991042 720000002774991044 $ awk -F, -v min=720000002774991000 -v max=720000002774991099 ' "" >= min && "" <= max \ && length() >= length(min) && length() <= length(max)' file 720000002774991065 720000002774991082 720000002774991070 720000002774991042 720000002774991044