grep的正则表达式问题

时间:2014-05-30 17:33:43

标签: regex bash sed grep

我正在尝试编写一个可以在CVS(Coma Separate Values)文件中找到一组电话号码的正则表达式。

Catch是我对特定列中的电话号码感兴趣(仅在特定数量的逗号后)。 Bellow我有正则表达式,它会按照Javascript标准运行。

(?:^([^^]*\,){3}[^^]*)\d{3}-\d{3}-\d{4}

我实际上是在使用sed工作并使用sed,grep,但是我甚至无法找到正则表达式grep和sed使用的内容?

以下是示例文本。

请注意,我现在使用'^'而不是','来保持值分开,因为用户在值中包含了逗号。

这不是实际数据,而是为了保护人们的隐私而加密

28434658^17 Three^2013-09-19T19:57:23Z^80 W 54th St, Penthouse & 4th Fl, NY, 10018s212-409-1641^^Mary Szyb 347-340-1918^2 x week Thur 2.5hrs  & Sat 4 hrs
28937693^356 West 36th street^2013-09-19T18:17:57Z^356 West 36th street, suite 706sNew York New York 10018^null^null^on call: 
29219313^333 rector pl^2013-10-07T17:11:36Z^333 Rector Place 248-469-5859^^Jose Hernandez^2 x week Wed & Fri
28854346^50 Can^2013-09-23T13:10:54Z^152 East 28th Street, 7th Floor, NY, 10018s917-932-3962s646-710-4170^155 W 24rd St 3rd FL^null^Swlvia Smith347-933-6630sIrena Brown 347-991-1346s5 x week Mon-Fri
28434698^4Eleven^2013-09-19T19:57:23Z^112 West 28th Street, 3th Fl,sNY, 10018s917-922-3862s646-710-4170^^null^null

我还要澄清正确输出的一件事:

212-409-1641
248-469-5859
917-932-3962
646-710-4170
917-922-3862
646-710-4170

因为这是第4栏中唯一的电话号码

4 个答案:

答案 0 :(得分:1)

以下内容适合您。

grep -Po '(\d{3}-){2}\d{4}' file.csv

<强>更新

用逗号替换^,因为它们在您实际数据中。

28434658,17 Three,2013-09-19T19:57:23Z,80 W 54th St, Penthouse & 4th Fl, NY, 10018s212-409-1641,Mary Szyb 347-340-1918,2 x week Thur 2.5hrs  & Sat 4 hrs
28937693,356 West 36th street,2013-09-19T18:17:57Z,356 West 36th street, suite 706sNew York New York 10018,null,null,on call: 
29219313,333 rector pl,2013-10-07T17:11:36Z,333 Rector Place 248-469-5859,Jose Hernandez,2 x week Wed & Fri
28854346,50 Can,2013-09-23T13:10:54Z,152 East 28th Street, 7th Floor, NY, 10018s917-932-3962s646-710-4170,155 W24rd St 3rd FL,null,Swlvia Smith347-933-6630sIrena Brown 347-991-1346s5 x week Mon-Fri
28434698,4Eleven,2013-09-19T19:57:23Z,112 West 28th Street, 3th Fl,sNY, 10018s917-922-3862s646-710-4170,null,null

您可以尝试以下操作。

perl -nle '@F = split(/,(?!s| )/, $_); print $1 while ($F[3] =~ /((\d{3}-){2}\d{4})/g)' file.csv

输出

212-409-1641
248-469-5859
917-932-3962
646-710-4170
917-922-3862
646-710-4170

答案 1 :(得分:0)

Grep可以将perl或posix标准与-P或-E一起使用。有关详细信息,请参阅 man grep 。对于这样的事情,我通常首先使用 cut 来分隔字段,假设没有字段会包含列分隔符。

echo "a,b,c,123-555-1212,d,e,f" | cut -f 4 -d','

或来自文件,

while read line; do
   c4=$(echo $line | cut -f 4 -d',')
done < /tmp/file.csv

如果任何列都可以包含逗号,那么您最好切换到ruby,python等中的CSV库。

更新:使用-d&#39; ^&#39;要分隔列,您可以非常轻松地匹配您感兴趣的列,如上所述,sed的棘手部分是提取电话号码,

f="80 W 54th St, Penthouse & 4th Fl, NY, 10018s212-409-1641"
echo $f | sed -r 's/(.*?)([0-9][0-9][0-9]-[0-9][0-9][0-9]-[0-9][0-9][0-9][0-9]$)/\2/'
212-409-1641

不是你必须使用扩展的正则表达式sed命令行参数(-r)似乎不能使用像\ d {3}这样的正则表达式文字。 sed的文档可以在信息页面找到,但通常更容易上网。这是一个非常好的教程:http://www.thegeekstuff.com/2009/10/unix-sed-tutorial-advanced-sed-substitution-examples/

答案 2 :(得分:0)

使用awk的答案:

awk -F'^' '{ 
  start = 0;
  str = substr($4, start);
  while (match(str, /([0-9]{3})-[0-9]{3}-[0-9]{4}/)) {
    print substr(str, RSTART, RLENGTH);
    start = RSTART + RLENGTH;
    str = substr(str, start);
  }
}' datafile

这将取第4列,重复匹配手机模式,然后将其打印出来。

答案 3 :(得分:0)

我发布了正在完成这项工作的正则表达式:

([0-9]{3}-[0-9]{3}-[0-9]{4})(?=[^^]*(\^[^^]*){3}$)

谢谢大家的有用输入

我想我从这个问题中得到的教训是,如果一个解决方案不起作用,尝试从不同角度工作,在这种情况下从后面计算列。