【问题标题】:Script returned '/usr/bin/awk: Argument list too long' in using -v in awk command在 awk 命令中使用 -v 时脚本返回“/usr/bin/awk:参数列表太长”
【发布时间】:2017-09-04 02:43:45
【问题描述】:

这是我的脚本中使用 awk 的部分。

ids=`cut -d ',' -f1 $file | sed ':a;N;$!ba;s/\n/,/g'`
awk -vdata="$ids" -F',' 'NR > 1 {if(index(data,$2)>0){print $0",true"}else{print $0",false"}}' $input_file >> $output_file

这很好用,但是当我尝试将数据获取到两个或更多这样的文件时。

ids=`cut -d ',' -f1 $file1 $file2 $file3 | sed ':a;N;$!ba;s/\n/,/g'`

它返回了这个错误。

/usr/bin/awk: Argument list too long

据我研究,这不是文件数量造成的,而是获取的 ids 数量造成的。

有人知道如何解决这个问题吗?谢谢。

【问题讨论】:

  • 你总是可以在awk 中执行cut 和sed,只需编写一个#!/bin/awk 脚​​本。
  • 你能举个例子说明你的输入数据和你的预期输出吗?我怀疑根本不需要cut 和sed。只需一个 awk 程序就足够了。

标签: bash csv awk


【解决方案1】:

您可以使用环境变量将数据传递给 awk。在 awk 中,可以通过数组 ENVIRON 访问环境变量。

所以尝试这样的事情:

export ids=`cut -d ',' -f1 $file | sed ':a;N;$!ba;s/\n/,/g'`
awk -F',' 'NR > 1 {if(index(ENVIRON["ids"],$2)>0){print $0",true"}else{print $0",false"}}' $input_file >> $output_file

【讨论】:

  • 我试过了,但仍然返回同样的错误。
【解决方案2】:

更改生成ids 的方式,使它们每行输出一个,就像这样,我用它作为生成ids 2,3 和9 的一种非常简单的方法:

echo 2; echo 3; echo 9
2
3
9

现在将它作为第一个文件传递给awk,将你的$input_file 作为第二个文件传递给awk:

awk '...' <(echo 2; echo 3; echo 9) "$input_file"

在bash 中,您可以使用&lt;(some commands) 生成带有进程输出的伪文件,这就是我正在使用的。

现在,在您的awk 中,从第一个文件中提取ids,如下所示:

awk 'FNR==NR{ids[$1]++;next}'  <(echo 2; echo 3; echo 9)

这将设置ids[2]=1、ids[3]=1 和ids[9]=1。

然后传递您的两个文件并添加您的原始处理:

awk 'FNR==NR{ids[$1]++;next} {if($2 in ids) print $0",true"; else print $0",false"}'  <(echo 2; echo 3; echo 9) "$input_file"

因此,对于我的最终答案,您的整个代码将如下所示:

awk 'FNR==NR{ids[$1]++;next} {if($2 in ids) print $0",true"; else print $0",false"}'  <(cut ... file1 file2 file3 | sed ...) "$input_file"

正如 @hek2mgl 在 cmets 中所暗示的那样,您可能只需将包含 ids 的文件传递给 awk “按原样” 并让 awk 找到 ids 本身而不是使用cut 和sed。如果有很多,你可以让他们都来awk作为第一个文件:

awk '...' <(cat file1 file2 file3) "$input_file"

【讨论】:

    【解决方案3】:

    您的脚本中有 2 个问题:

    awk -vdata="$ids" -F',' 'NR > 1 {if(index(data,$2)>0){print $0",true"}else{print $0",false"}}' $input_file >> $output_file
    

    这可能会导致该错误:

    1. -vdata=.. - 这是 gawk 特有的,在其他 awk 中,您需要在 -v 和 data= 之间留一个空格。因此,如果您没有运行 gawk,那么请了解您的 awk 对该语句的看法,但它可能会将其视为多个参数。
    2. $input_file - 你必须引用 shell 变量,除非你有特定的目的,不加引号。如果$input_file 包含通配符或空格,那么不加引号将导致它们扩展为可能的多个文件/参数。

    所以试试这个:

    awk -v data="$ids" -F',' 'NR > 1 {if(index(data,$2)>0){print $0",true"}else{print $0",false"}}' "$input_file" >> "$output_file"
    

    看看你是否还有问题。当然,您的脚本确实有其他不相关的问题,其中一些已经被指出,如果您需要帮助,您可以发布后续问题,但仅供参考,awk 脚本可以更简洁地编写为:

    awk -v data="$ids" 'BEGIN{FS=OFS=","} NR > 1{print $0, (index(data,$2) ? "true" : "false")}'
    

    【讨论】:

    • 我尝试了您的两个建议,但都没有奏效。它仍然返回“/usr/bin/awk: Argument list too long”错误。
    • 那么你在调用 awk 的 shell 脚本的其他地方有一个 bug。您将 1 字符串作为 data 和 1 文件名传递 - 鉴于此,awk 绝不会认为参数太多。在你的 shell 脚本上运行shellcheck,特别是寻找不匹配的引号。
    猜你喜欢
    • 2015-01-17
    • 1970-01-01
    • 2014-08-30
    • 2015-04-27
    • 2018-07-24
    • 1970-01-01
    • 2016-09-11
    • 2015-03-21
    • 2021-11-16
    相关资源
    最近更新 更多