在awk中调用system()时出错

时间:2014-07-16 08:30:54

标签: bash shell awk syntax-error

我正在尝试执行系统命令,以查找csv文件在其前七个字符中有多少唯一引用,作为处理相同csv文件的较大awk脚本的一部分。有重复的条目,我不希望awk解析整个文件两次,所以我避免NR。脚本这一部分的要点是:

#!/bin/bash
awk '
{
  #do some stuff, then when finished, count the number of unique references
  productFile="BusinessObjects.csv";
  systemCall = sprintf( "cat %s | cut -c 1-7 | sort | uniq | wc -l", $productFile );
  productCount=`system( systemCall )`-1; #subtract 1 to remove column label row
}' < BusinessObjects.csv

翻译不喜欢它:

awk: cmd. line:19: ^ syntax error ./awkscript.sh: line 38: syntax error near unexpected token '(' ./awkscript.sh: line 38: systemCall = sprintf( "cat %s | cut -c 1-7 | sort | uniq | wc -l", $productFile );

如果我硬编码系统命令

productCount=`system( "cat BusinessObjects.csv | cut -c 1-7 | sort | uniq | wc -l" )`-1;

我明白了:

./awkscript.sh: command substitution: line 39: syntax error near unexpected token '"cat BusinessObjects.csv | cut -c 1-7 | sort | uniq | wc -l"' ./awkscript.sh: command substitution: line 39: 'system( "cat BusinessObjects.csv | cut -c 1-7 | sort | uniq | wc -l" )'

从技术上讲,我可以在shell脚本开始时在awk之外执行此操作,将结果存储在系统变量中,然后使用-v将其传递给awk,但这对于awk脚本的可读性并不好(这是几百行长)。我在错误的地方有空格或引号吗?我试过摆弄,但我似乎无法以解释器接受的方式呈现对system()的调用。最后,还有更合理的方法吗?


编辑: csv文件确实是以分号分隔的,所以最好使用分隔符而不是字符数来剪切(谢谢!)。

  

ProductRef;数据1;数据2;等等

     

1234567;等;等;等等


编辑2: 我正在尝试解析第一列充满N个唯一产品引用的csv文件,并创建一系列包含“Page n of N”信息字段的关联HTML页面。很明显,这是我第一次使用awk,但它似乎是解析csv文件的合适工具。我正在尝试计算并返回唯一引用的数量。在shell

  

cut -d \; -f1 BusinessObjects.csv |排序| uniq | wc -l <​​/ p>

工作正常,但我无法通过

让它在awk中运行
#!/bin/bash
if [ -n "$1" ]
then
        productFile=$1
else
        echo "Missing product file argument."
        exit
fi

awk -v productFile=$productFile '
BEGIN {
        FS=";";
        productCount = 0;
        ("cut -d\"\;\" -f1 " productFile " | sort | uniq | wc -l") | getline productCount;
        productCount -=1; #remove the column label row
}

{
print productCount;
}'

如果我没有将分号包装在\“\; \”中,我会在剪切代码上出现语法错误,而且当我这样做时,脚本会挂起而不打印任何内容。

2 个答案:

答案 0 :(得分:1)

我不记得你可以在awk中使用反引号。

  productCount=`system( systemCall )`-1; #subtract 1 to remove column label row

您可以通过不使用系统并直接运行命令来读取输出,而是使用getline:

  systemCall | getline productCount
  productCount -= 1

或者更完整

  productFile = "BusinessObjects.csv"
  systemCall = "cut -c 1-7 " productFile " | sort | uniq | wc -l"
  systemCall | getline productCount
  productCount -= 1
  • 无需使用sprintf并包含cat
  • 将字符串分配给变量也是可选的。你可以"xyz" | getline ...
  • 如果支持,
  • sort | uniq可以sort -u
  • 如果filename包含可能会混淆命令的空格或字符,则可能需要引用。
  • getline可能会改变全局变量与预期不同。见https://www.gnu.org/software/gawk/manual/html_node/Getline.html

答案 1 :(得分:0)

这样的事情可以选择吗?

$ cat productCount.sh
#!/bin/bash
if [ -n "$1" ]
then
        productCount=`cat $1 | cut -c 1-7 | sort | uniq | wc -l`
        echo $productCount
else
        echo "please supply a filename as parameter"
fi

$ ./productCount.sh BusinessObjects.csv
9