gawk中的下一个命令没有产生预期的结果

时间:2017-09-18 21:23:26

标签: awk gawk

我试图跳过一堆制表符分隔的文本文件的第一部分。 (我转换为以逗号分隔的样本数据。)我似乎无法弄清楚为什么这不起作用:

CODE

gawk '
  /[^Country Of Sale]/ {next}
  /^Cloud Total/ {nextfile}
  FNR > 1 {$0 =  FILENAME OFS $0; print}
' OFS='\t' /path/to/files/*.txt > path/to/new_file.txt

DATA

"Start Date","End Date","UPC" "4/2/17","5/6/17","SKIP THIS LINE"
"4/2/17","5/6/17","SKIP THIS LINE" "4/2/17","5/6/17","SKIP THIS LINE"
"4/2/17","5/6/17","SKIP THIS LINE" "4/2/17","5/6/17","SKIP THIS LINE"
"Row Count","447","SKIP THIS LINE" 
"Country Of Sale","Total","Total  Units1","Total Units2","Total C_F","SPCU","PCUT","CPS","USPS","Total  Share","EffSUBS","ActSUBS"
"AU","0","139851331","139851331","195833.36","0.001400297","1170","1.36","","1.36","91704.63","99430"
"Cloud Total","1.36" "Sales Total","243.18" "Total Amount","244.54"

预期输出

"Country Of Sale","Total","Total  Units1","Total Units2","Total C_F","SPCU","PCUT","CPS","USPS","Total  Share","EffSUBS","ActSUBS"
"AU","0","139851331","139851331","195833.36","0.001400297","1170","1.36","","1.36","91704.63","99430"

另外,我想制作销售国家"排列所有文件的标题。但NR& FNR从头开始计算。鉴于"销售国家"我该怎么做呢?在每个文件中出现在不同的行号中?

感谢您的帮助!

3 个答案:

答案 0 :(得分:2)

[...]是一个括号表达式,包括一个列表,一组或一系列字符。它不包含字符串或字符串的否定。

[^Country Of Sale] = [^aCFelnoOrStuy]

当你可能意味着:

!/Country Of Sale/

仍然不是你真正需要的。试试这个:

gawk '
  BEGIN { FS=OFS="\t" }
  /Country Of Sale/ { f=1 }
  /Cloud Total/ { f=0; nextfile }
  f { print FILENAME, $0 }
' RAW/iTunes/iTunesMatch/*.txt > munched/iTunesMatch_TEST.txt

查找

$ cat file
"Start Date","End Date","UPC" "4/2/17","5/6/17","SKIP THIS LINE"
"4/2/17","5/6/17","SKIP THIS LINE" "4/2/17","5/6/17","SKIP THIS LINE"
"4/2/17","5/6/17","SKIP THIS LINE" "4/2/17","5/6/17","SKIP THIS LINE"
"Row Count","447","SKIP THIS LINE"
"Country Of Sale","Total","Total  Units1","Total Units2","Total C_F","SPCU","PCUT","CPS","USPS","Total  Share","EffSUBS","ActSUBS"
"AU","0","139851331","139851331","195833.36","0.001400297","1170","1.36","","1.36","91704.63","99430"
"Cloud Total","1.36" "Sales Total","243.18" "Total Amount","244.54"

$ gawk '
   BEGIN { FS=OFS="\t" }
   /Country Of Sale/ { f=1 }
   /Cloud Total/ { f=0; nextfile }
   f { print FILENAME, $0 }
' file
file    "Country Of Sale","Total","Total  Units1","Total Units2","Total C_F","SPCU","PCUT","CPS","USPS","Total  Share","EffSUBS","ActSUBS"
file    "AU","0","139851331","139851331","195833.36","0.001400297","1170","1.36","","1.36","91704.63","99430"

如果您有多个输入文件并且只想要销售国家/地区一行,那么一种方法就是:

$ gawk '
   BEGIN { FS=OFS="\t" }
   /Country Of Sale/ { f=1; if (NR==FNR) print FILENAME, $0; next}
   /Cloud Total/ { f=0; nextfile }
   f { print FILENAME, $0 }
' file file file
file    "Country Of Sale","Total","Total  Units1","Total Units2","Total C_F","SPCU","PCUT","CPS","USPS","Total  Share","EffSUBS","ActSUBS"
file    "AU","0","139851331","139851331","195833.36","0.001400297","1170","1.36","","1.36","91704.63","99430"
file    "AU","0","139851331","139851331","195833.36","0.001400297","1170","1.36","","1.36","91704.63","99430"
file    "AU","0","139851331","139851331","195833.36","0.001400297","1170","1.36","","1.36","91704.63","99430"

答案 1 :(得分:2)

正如我在评论中所指出的那样,/[^Country Of Sale]/可能并没有做你认为应该做的事情。提示:其中一个重复的空白是多余的。 (碰巧的是,空白是该否定字符类中唯一重复的字符。)

它实际上做的是查找除[ COSaeflnortuy]之一之外的任何字符(方括号是元字符),如果找到一个,则跳转到下一行。例如,如果该行包含双引号或逗号,它将跳转到下一行输入(因为方括号中既没有双引号也没有逗号)。

请注意,在您的CSV数据中," Cloud Total"不会以C开头;它以双引号开头。不幸的是,正在搜索它的正则表达式坚持C必须是第一个字符。

我认为你需要这样的东西:

gawk 'FNR==1,/Country Of Sale/ { next }
      /Cloud Total/ { nextfile }
      { print }' data

只列出给定数据中的AU行(如果在单个命令行上列出相同的文件3次,则会得到3行以AU开头,因此它可以在文件中正常工作,部分原因在于范围FNR==1,/…/)。

你应该可以从那里拿走它。如果您愿意,可以使模式更具限制性(/^"Country Of Sale",/等)。您可以使用{ print FILENAME OFS $0 }打印以文件名和输出字段分隔符(命令行中的选项卡)为前缀的行。

  

这个,以及@ Ed的建议,都提供所有的数据行,而不仅仅是"销售国家"和" Cloud Total"。

这就是我得到的(在Mac上运行macOS Sierra 10.12.6,使用自制的GNU Awk 4.1.3, API: 1.1):

$ cat data
"Start Date","End Date","UPC" "4/2/17","5/6/17","SKIP THIS LINE"
"4/2/17","5/6/17","SKIP THIS LINE" "4/2/17","5/6/17","SKIP THIS LINE"
"4/2/17","5/6/17","SKIP THIS LINE" "4/2/17","5/6/17","SKIP THIS LINE"
"Row Count","447","SKIP THIS LINE" 
"Country Of Sale","Total","Total  Units1","Total Units2","Total C_F","SPCU","PCUT","CPS","USPS","Total  Share","EffSUBS","ActSUBS"
"AU","0","139851331","139851331","195833.36","0.001400297","1170","1.36","","1.36","91704.63","99430"
"Cloud Total","1.36" "Sales Total","243.18" "Total Amount","244.54"
$ gawk 'FNR==1,/Country Of Sale/{next} /Cloud Total/ {nextfile} { print }' data data data
"AU","0","139851331","139851331","195833.36","0.001400297","1170","1.36","","1.36","91704.63","99430"
"AU","0","139851331","139851331","195833.36","0.001400297","1170","1.36","","1.36","91704.63","99430"
"AU","0","139851331","139851331","195833.36","0.001400297","1170","1.36","","1.36","91704.63","99430"
$

鉴于我已经将文件处理了3次,这就是我所期望的并且似乎是您想要的。

如果你想要"销售国家"输出中的标题行,可以很容易地添加:

gawk 'FNR==1,/Country Of Sale/ { if ($0 ~ /Country Of Sale/) print; next }
      /Cloud Total/ { nextfile }
      { print }' data

即使它出现在许多文件中,如果你只想要一次标题,那么:

gawk 'FNR==1,/Country Of Sale/ { if ($0 ~ /Country Of Sale/ && hdr_count++ == 0) print; next }
      /Cloud Total/ { nextfile }
      { print }' data

答案 2 :(得分:-1)

感谢@EdMorton @@JonathanLeffler为我提供了必要的线索。最终工作的是使用/^Country Of Sale/{next}& /^Cloud Total/ {nextfile}。接下来,我将弄清楚 *为什么* 这确实有效!