免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 6446 | 回复: 17
打印 上一主题 下一主题

新人求助 面试时 perl正则匹配题 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2017-06-25 19:56 |只看该作者 |倒序浏览
本帖最后由 myuanzhao 于 2017-06-25 19:57 编辑

在面试时遇到这么一道题:
以下是一个文件的一部分:
block1
    LAYER1
        a0=56, b0=147.345989944561, c0=11.0225098942223
        a1=76, b1=174.434168420681, c1=253.89644118973
        a2=42, b2=117.774925865152, c2=182.422622167185
    LAYER2
        a0=48, b0=164.391521356056, c0=243.612268442083
        a1=56, b1=56.3028265552006, c1=67.3497698774622
        a2=17, b2=182.182082410397, c2=265.689705668802
block2
    LAYER1
        a0=13, b0=98.5005938116799, c0=193.432038047288
        a1=32, b1=173.682215090149, c1=284.746973938173
        a2=80, b2=77.3396633455278, c2=45.913625227217
    LAYER2
        a0=89, b0=6.78883867591011, c0=181.63053325133
        a1=35, b1=51.962410302621, c1=114.479466051294
        a2=57, b2=88.5057901717936, c2=119.906443042102
    LAYER3
        a0=22, b0=135.172781428776, c0=180.32730953417
        a1=89, b1=38.4925211497517, c1=171.120129693275
        a2=53, b2=102.546819074468, c2=235.02212266283
        a3=5, b3=46.5476781394699, c3=69.2620776701364
block3  
     ..........
     ..........
要求利用perl,shell,tcl等语言将block2中的LAYER1和LAYER2中的内容替换为NEED TO REBUILD,替换后如下:

block1
    LAYER1
        a0=56, b0=147.345989944561, c0=11.0225098942223
        a1=76, b1=174.434168420681, c1=253.89644118973
        a2=42, b2=117.774925865152, c2=182.422622167185
    LAYER2
        a0=48, b0=164.391521356056, c0=243.612268442083
        a1=56, b1=56.3028265552006, c1=67.3497698774622
        a2=17, b2=182.182082410397, c2=265.689705668802
block2
    LAYER1
        NEED TO REBULID
    LAYER2
        NEED TO REBULID
    LAYER3
        a0=22, b0=135.172781428776, c0=180.32730953417
        a1=89, b1=38.4925211497517, c1=171.120129693275
        a2=53, b2=102.546819074468, c2=235.02212266283
        a3=5, b3=46.5476781394699, c3=69.2620776701364
block3  
     ..........
我自己的代码如下:
use strict;
my $file_dir="./generated_file";
my $str;
my $block_flag=0;
my $layer_flag=0;
open (IN,"<",$file_dir);
while(<IN>){
  $block_flag=0 if ($block_flag && $_=~/^[\w]*$/);
  $block_flag=1 if ($_=~/^block2/);
  if($block_flag && $_=~/^\tLAYER[12]/){
    $layer_flag=1;
    $str.=$_;
    $str.="\t\tNEED to REBUILD\n";
    next;
  }
  if($layer_flag && $_=~/LAYER/){
    $layer_flag=0;
  }
  next if($layer_flag);
  $str.=$_;
}
close IN;
print $str;

面试官说我写的不好,我想了好久,也没什么好的想法,向各位大神请教,请问我的问题出在哪里了?或者说能不能有更简洁的方法来操作?

论坛徽章:
12
子鼠
日期:2014-10-11 16:46:482016科比退役纪念章
日期:2018-03-16 10:24:0515-16赛季CBA联赛之山东
日期:2017-11-10 14:32:142016科比退役纪念章
日期:2017-09-02 15:42:4715-16赛季CBA联赛之佛山
日期:2017-08-28 17:11:5515-16赛季CBA联赛之浙江
日期:2017-08-24 16:55:1715-16赛季CBA联赛之青岛
日期:2017-08-17 19:55:2415-16赛季CBA联赛之天津
日期:2017-06-29 10:34:4315-16赛季CBA联赛之四川
日期:2017-05-16 16:38:55黑曼巴
日期:2016-07-19 15:03:112015亚冠之萨济拖拉机
日期:2015-05-22 11:38:5315-16赛季CBA联赛之北京
日期:2019-08-13 17:30:53
2 [报告]
发表于 2017-06-25 20:17 来自手机 |只看该作者
等等,你在哪里面试的?求推荐用perl的公司

论坛徽章:
12
子鼠
日期:2014-10-11 16:46:482016科比退役纪念章
日期:2018-03-16 10:24:0515-16赛季CBA联赛之山东
日期:2017-11-10 14:32:142016科比退役纪念章
日期:2017-09-02 15:42:4715-16赛季CBA联赛之佛山
日期:2017-08-28 17:11:5515-16赛季CBA联赛之浙江
日期:2017-08-24 16:55:1715-16赛季CBA联赛之青岛
日期:2017-08-17 19:55:2415-16赛季CBA联赛之天津
日期:2017-06-29 10:34:4315-16赛季CBA联赛之四川
日期:2017-05-16 16:38:55黑曼巴
日期:2016-07-19 15:03:112015亚冠之萨济拖拉机
日期:2015-05-22 11:38:5315-16赛季CBA联赛之北京
日期:2019-08-13 17:30:53
3 [报告]
发表于 2017-06-25 20:17 来自手机 |只看该作者
等等,你在哪里面试的?求推荐用perl的公司

论坛徽章:
0
4 [报告]
发表于 2017-06-25 21:28 |只看该作者
回复 3# 523066680
芯片行业好多在用,数字芯片常用的工具

论坛徽章:
12
子鼠
日期:2014-10-11 16:46:482016科比退役纪念章
日期:2018-03-16 10:24:0515-16赛季CBA联赛之山东
日期:2017-11-10 14:32:142016科比退役纪念章
日期:2017-09-02 15:42:4715-16赛季CBA联赛之佛山
日期:2017-08-28 17:11:5515-16赛季CBA联赛之浙江
日期:2017-08-24 16:55:1715-16赛季CBA联赛之青岛
日期:2017-08-17 19:55:2415-16赛季CBA联赛之天津
日期:2017-06-29 10:34:4315-16赛季CBA联赛之四川
日期:2017-05-16 16:38:55黑曼巴
日期:2016-07-19 15:03:112015亚冠之萨济拖拉机
日期:2015-05-22 11:38:5315-16赛季CBA联赛之北京
日期:2019-08-13 17:30:53
5 [报告]
发表于 2017-06-25 21:47 |只看该作者
本帖最后由 523066680 于 2017-06-25 22:04 编辑
  1. use File::Slurp;

  2. my $text = read_file('block.txt');
  3. my $NTR = "NEED TO REBUILD";

  4. $text =~s/(block2\s+LAYER1\s+).*?(\s+LAYER2)/$1$NTR$2/si;
  5. $text =~s/(block2\s+.*?LAYER2\s+).*?(\s+LAYER3)/$1$NTR$2/si;

  6. print $text;
复制代码

一些建议,如果使用类 C语言,左边花括号最好换行。面试官看代码印象分+1(除非他是异教徒
像下面的句子,该空格的地方空格,该换行的换行,不要太拥挤。

if($block_flag && $_=~/^\tLAYER[12]/){}

可以写成

if ( xxx   and   xxx )
{

}

甚至是:

if (
    xxxxxxxxxxxx
     and
    xxxxxxxxxxxx
   )
{

}

我是业余党,在外贸公司打杂,工作和编程毛关系都没有,但是我很注重风格,严于律己。
最后,思考问题要看到全局,这个问题可以锚定前后关键字,中间直接替换,无需 while 循环。

论坛徽章:
145
技术图书徽章
日期:2013-10-01 15:32:13戌狗
日期:2013-10-25 13:31:35金牛座
日期:2013-11-04 16:22:07子鼠
日期:2013-11-18 18:48:57白羊座
日期:2013-11-29 10:09:11狮子座
日期:2013-12-12 09:57:42白羊座
日期:2013-12-24 16:24:46辰龙
日期:2014-01-08 15:26:12技术图书徽章
日期:2014-01-17 13:24:40巳蛇
日期:2014-02-18 14:32:59未羊
日期:2014-02-20 14:12:13白羊座
日期:2014-02-26 12:06:59
6 [报告]
发表于 2017-06-25 21:53 |只看该作者
回复 1# myuanzhao

只看主要程序部分,程序做什么 !!??

while(<IN>){
  $block_flag=0 if ($block_flag && $_=~/^[\w]*$/);
  $block_flag=1 if ($_=~/^block2/);
  if($block_flag && $_=~/^\tLAYER[12]/){
    $layer_flag=1;
    $str.=$_;
    $str.="\t\tNEED to REBUILD\n";
    next;
  }
  if($layer_flag && $_=~/LAYER/){
    $layer_flag=0;
  }
  next if($layer_flag);
  $str.=$_;
}

论坛徽章:
0
7 [报告]
发表于 2017-06-25 23:49 |只看该作者
写一个,不一定比你的好。
  1. use strict;
  2. open (IN,"<","generated_file");
  3. open (OUT,">","generated_file2");
  4. my $block_flag2=0;
  5. my $layer_flag=0;

  6. while(<IN>)
  7. {   
  8.          if($_=~/^\s*[bl]/i)#block、layer行
  9.          {
  10.                    print OUT  $_; #block、layer行全部保留
  11.                    if ($_=~/block2/)
  12.                    {
  13.                            $block_flag2=1;
  14.                    }elsif($_=~/block3/)
  15.                    {
  16.                            $block_flag2=0;
  17.                    }
  18.                    
  19.            if ($block_flag2 && $_=~/^\s*LAYER[12]/)
  20.            {
  21.                             print OUT "          NEED to REBUILD\n"; #新增行
  22.                             $layer_flag=1;#标志删除后面行
  23.            }elsif ($_=~/^\s*LAYER3/)
  24.            {
  25.                      $layer_flag=0;
  26.            }
  27.                    
  28.          }elsif($layer_flag)
  29.          {          
  30.            #删除行
  31.          }else
  32.          {
  33.                    print OUT $_;#其余数据行保留
  34.          }   
  35. }
  36. close IN;
  37. close OUT;

复制代码

论坛徽章:
307
程序设计版块每周发帖之星
日期:2016-04-08 00:41:33操作系统版块每日发帖之星
日期:2015-09-02 06:20:00每日论坛发贴之星
日期:2015-09-02 06:20:00程序设计版块每日发帖之星
日期:2015-09-04 06:20:00每日论坛发贴之星
日期:2015-09-04 06:20:00每周论坛发贴之星
日期:2015-09-06 22:22:00程序设计版块每日发帖之星
日期:2015-09-09 06:20:00程序设计版块每日发帖之星
日期:2015-09-19 06:20:00程序设计版块每日发帖之星
日期:2015-09-20 06:20:00每日论坛发贴之星
日期:2015-09-20 06:20:00程序设计版块每日发帖之星
日期:2015-09-22 06:20:00程序设计版块每日发帖之星
日期:2015-09-24 06:20:00
8 [报告]
发表于 2017-06-26 00:23 |只看该作者
  1. #!/usr/bin/perl
  2. use strict;
  3. use warnings;

  4. local $/ = "\nblock";
  5. my @aPair = ("    LAYER", "NEED TO REBULID\n");
  6. while(<DATA>){
  7.         chomp;
  8.         (my $n, local $_) = split(/\n/, $_, 2);
  9.         $n =~ /(\d+)/ and print("block$1\n");
  10.         if($1 == 2 and /^(\s*LAYER3.*)/ms){
  11.                 $_ = sprintf("%s1\n\t%s%s2\n\t%s$1", @aPair, @aPair);
  12.         }
  13.         print("$_\n");
  14. }

  15. __DATA__
  16. block1
  17.     LAYER1
  18.         a0=56, b0=147.345989944561, c0=11.0225098942223
  19.         a1=76, b1=174.434168420681, c1=253.89644118973
  20.         a2=42, b2=117.774925865152, c2=182.422622167185
  21.     LAYER2
  22.         a0=48, b0=164.391521356056, c0=243.612268442083
  23.         a1=56, b1=56.3028265552006, c1=67.3497698774622
  24.         a2=17, b2=182.182082410397, c2=265.689705668802
  25. block2
  26.     LAYER1
  27.         a0=13, b0=98.5005938116799, c0=193.432038047288
  28.         a1=32, b1=173.682215090149, c1=284.746973938173
  29.         a2=80, b2=77.3396633455278, c2=45.913625227217
  30.     LAYER2
  31.         a0=89, b0=6.78883867591011, c0=181.63053325133
  32.         a1=35, b1=51.962410302621, c1=114.479466051294
  33.         a2=57, b2=88.5057901717936, c2=119.906443042102
  34.     LAYER3
  35.         a0=22, b0=135.172781428776, c0=180.32730953417
  36.         a1=89, b1=38.4925211497517, c1=171.120129693275
  37.         a2=53, b2=102.546819074468, c2=235.02212266283
  38.         a3=5, b3=46.5476781394699, c3=69.2620776701364
  39. block3
  40.     LAYER1
  41.         a0=89, b1=38.4925211497517, c1=171.120129693299
  42.         a1=53, b2=102.546819074468, c2=235.02212266299
复制代码

论坛徽章:
0
9 [报告]
发表于 2017-06-26 21:45 |只看该作者
回复 5# 523066680
谢谢您的指导,perl模块真的好用好多,如果遇到一个问题,如何去找对应的模块呢?只能通过平时积累吗?

论坛徽章:
0
10 [报告]
发表于 2017-06-26 23:05 |只看该作者
回复 8# sunzhiguolu
谢谢您的指导
我之前有想过用split划分模块,将整个文件化成不同的block,但具体操作时就不知道怎么入手了。
第一次知道split可以用的这么巧妙,感觉一下子还没有领悟的很好,可能还会有一些问题,希望您能指点,


您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP