awk匹配字段与变量正则表达式

时间:2016-02-03 22:54:15

标签: regex bash awk

我需要根据(半任意)位置对一系列.csv患者人口统计报告进行排序,如邮政编码所示。

我编写了一个解析文件的bash脚本,该文件列出了所有诊所及其分配的邮政编码。但是,我无法弄清楚如何将正则表达式编码到我的awk语句中。

邮政编码文件:

$   cat clinics
south;23456|23458|23451
north;23452|23454|23459
west;23453|23455|23457

示例数据文件:

$   head sample.csv
FirstName,LastName,MiddleName,Address,City,State,Zip,Plus4,Phone,MoveDate,OwnerShip,EstValue,ChildCode,MailInd,MoveDist,Age,Income
John,Smith,,123 Main Street,Hudson,NC,23456,1234,5555555555,01/03/2004,0,03,0,0,0,0,05
Jim,Smith,,123 Main Street,Lenoir,NC,23457,1234,5555555555,01/03/2004,3,03,0,0,0,0,06
Joe,Smith,,123 Main Street,Greensboro,NC,23457,1234,5555555555,01/03/2004,3,02,4,1,0,4,08
Jimmy,Smith,,123 Main Street,Statesville,NC,23457,1234,5555555555,01/03/2004,3,05,2,1,1,2,13
Jimmy,Smits,,123 Main Street,Charlotte,NC,23456,1234,5555555555,01/03/2004,3,04,1,1,4,4,18
J Jonah,Smith,,123 Main Street,Fayetteville,NC,23458,1234,5555555555,01/03/2004,3,03,1,1,3,4,01
James,Smith,,123 Main Street,Maiden,NC,23459,1234,5555555555,01/03/2004,3,00,4,1,0,2,18
Jahosephat,Smith,,123 Main Street,Hudson,NC,23459,1234,5555555555,01/03/2004,3,00,4,1,0,1,02
Jane,Smith,,123 Main Street,Charlotte,NC,23451,1234,5555555555,01/03/2004,3,05,4,1,0,3,06

将诊所与其邮政编码相关联很容易。我可以使用awk和正则表达式匹配南方诊所:

$   awk -F, '$7 ~ "23456|23458|23451"' sample.csv
John,Smith,,123 Main Street,Hudson,NC,23456,1234,5555555555,01/03/2004,0,03,0,0,0,0,05
Jimmy,Smits,,123 Main Street,Charlotte,NC,23456,1234,5555555555,01/03/2004,3,04,1,1,4,4,18
J Jonah,Smith,,123 Main Street,Fayetteville,NC,23458,1234,5555555555,01/03/2004,3,03,1,1,3,4,01
Jane,Smith,,123 Main Street,Charlotte,NC,23451,1234,5555555555,01/03/2004,3,05,4,1,0,3,06

然而,当我尝试替换一个字符串变量(就像我的脚本必须这样)时,我无法弄清楚如何转义变量,所以awk喜欢它:

$   Zips="23456|23458|23451"
$   awk -F, '$7 ~ "$Zips"' sample.csv
$   awk -F, '$7 ~ /$Zips/' sample.csv
$   awk -F, '$7 ~ /\$Zips/' sample.csv
$   awk -F, '$7 ~ /\\$Zips/' sample.csv
$

更新:

除了让awk解析变量之外,我还尝试为它提供一个shell扩展变量;那是行不通的,但我知道自己错了以后 (感谢@haifzhan和@EdMorton)。

我试过

awk -F, "\$7 ~ $Zips" sample.csv
awk -F, '$7 ~ '"\"/$Zips/\"" sample.csv
awk -F, '{$7 ~ ' "/$Zips/" ' }' sample.csv

和十几个类似的排列。我现在明白这对awk的能力非常不了解,因此我很高兴我没有想到@ EdMorton在评论中提出的建议 - 尽管我很生气但我并没有这样做。想到这一点 - 因为我对awk的了解并没有得到改善。每次尝试都返回null或失败并显示错误:

awk: syntax error at source line 1
 context is
    {$7 ~ >>>  23456\ <<< 23458|23451}
awk: bailing out at source line 1

更新(grep):我发现了我的逻辑(不是语法)疏忽,如果不能使现有的评论不一致,我会删除此部分...

我尝试grep,错误地假设我的测试正确缩放 - 它没有。

grep -E ','"$Zips"',' $SrcFile >> $OutFile

(意思是)

match any of:
",23456"
"23458"
"23451,"

对于我的50行样本文件,grepawk之间的结果是相同的,但实际的8000行文件恰好包含了我所担心的匹配类型。

感谢大家的阅读。

3 个答案:

答案 0 :(得分:2)

使用awk -F, -v zips="23456|23458|23451" '$7 ~ zips' sample.csv 声明varialbe

counter

答案 1 :(得分:0)

要按照您的说法直接执行此操作,您需要使用双引号来替换Error: no such instruction:,然后使用&#39; \&#39;来转义某些字符:

$Zips

答案 2 :(得分:-2)

你必须正确引用你的报价。在单引号内没有发生shell变量扩展。你有整个awk程序的单引号。但是当你像grep示例中那样放置引号时它会起作用:单引号包围所有内容,除了shell变量,它必须是双引号(展开)以保护shell的管道字符:

awk -F, '$7 ~ '"/$Zips/" sample.csv

这给出了结果:

$ awk -F, '$7 ~ '"/$Zips/" sample.csv 
John,Smith,,123 Main Street,Hudson,NC,23456,1234,5555555555,01/03/2004,0,03,0,0,0,0,05
Jimmy,Smits,,123 Main Street,Charlotte,NC,23456,1234,5555555555,01/03/2004,3,04,1,1,4,4,18
J Jonah,Smith,,123 Main Street,Fayetteville,NC,23458,1234,5555555555,01/03/2004,3,03,1,1,3,4,01
Jane,Smith,,123 Main Street,Charlotte,NC,23451,1234,5555555555,01/03/2004,3,05,4,1,0,3,06