大家好!请问用什么办法能把这段文本拆解啊?

楼上的朋友,我理解你的思路,但其实那种办法有缺陷,其实那份文档的语法可以是这样的
PSDSS249 =  (DESCRIPTION =   (ADDRESS_LIST =  (ADDRESS = (PROTOCOL = TCP)(HOST = 10.136.33.249)(PORT = 1521))
    )
    (CONNECT_DATA =  (SERVICE_NAME = PSDSS)
    )
  )

所以我觉得还得用redspider网友提的那种思路,我能猜出来,他的想法比较先进,不过还是谢了!如果全是我发的那种文档编排你的代码就行了!
#! /usr/bin/perl

use warnings;
use strict;

my @data;
my $stack_point = 0;

# 每段数据开头的标识处理我不写了

# ........


open(FILE, 'file') or die $!;
while (<FILE>) {
    my @characters = split(//);

    for my $c (@characters) {
        push(@data, $c);
        if ($c eq '(') { $stack_point++ }
        elsif ($c eq ')') { $stack_point-- }

        if ($stack_point == 0) {
            # $stack_point 计数为 0 说明一段数据读完

            # 数据在 @data 中,这里该咋办咋办


            @data = (); # 办完后清空

        }
    }
}
close FILE;


刚改了两行代码。说不上先进,别人几十年前发明的。
还是彩色的代码看着爽 , 顺便说下,偶不用 MSN

谢谢!兄弟,到大连的话跟我联系啊!我请客,我自己试验试验
又偷学了一招 ~~~~~
#! /usr/bin/perl

use warnings;
use strict;

my @data;
my $stack_point = 0;
my $temp_str;
my $begin_paragraph = 1;

my $name;
my $host;
my $port;
my $service_name;

   
open(FILE, 'c:\tnsnames.ora') or die $!;

while (<FILE>) {
    chomp();
    $_ =~ s/^\s+//;
    $_ =~ s/\s+$//;
#    next if(($_ =~ /^#/) || ($_ = ""));
   
    my @characters = split(//);

    for my $c (@characters) {
        push(@data, $c);
        if ($c eq '(') { $stack_point++ }
        elsif ($c eq ')') { $stack_point-- }

        if ($stack_point == 0) {
                  my $temp_str = join('', @data);
            if($begin_paragraph == 1){
                if($temp_str =~ /^(\w+)\s*=\s*.*/){ #这部分总匹配不了呢?
                    $name = $1;
                    printf("%30s", $name);
                }
                $begin_paragraph = 0;
            }
            
            if($temp_str =~ /HOST\s*=\s*([\d\.]+)\)/){
                $host = $1;
                printf("%20s", $host);
            }
            
            if($temp_str =~ /PORT\s*=\s*(\d+)\)/){
                      $port = $1;
                      printf("%10s", $port);
            }
            
            if($temp_str =~ /SERVICE_NAME\s*=\s*(\S+)\s*\)/){
                $service_name = $1;
                printf("%20s\n", $service_name);
                $begin_paragraph = 1;
            }
            
            @data = ();
        }
    }
}

close FILE;

结果如下,name没打出来,结尾还多了两个)呢

C:\>perl e.pl
       10.136.33.249      1521             PSDSS))
       10.136.33.248      1521             PSDSS))      
      10.136.36.120      1521               mis))
perl -ne '"chomp;print "\n" if /^\S+/;print' youfile|perl -e "print ... if ... (模式匹配)..."
下面是最终完美版!

#! /usr/bin/perl


use warnings;
use strict;

my @data;
my $stack_point = 0;
my $temp_str='';
my $begin_paragraph = 1;

my $name;
my $host;
my $port;
my $service_name;

    
open(FILE, 'c:\tnsnames.ora') or die $!;
my @characters;
while (<FILE>) {
    chomp();
    next if(($_=~ /^\s*$/) || ($_=~ /^#/));

    
    @characters = split(//);
     
    for my $c (@characters) {
        $temp_str .= $c;
        if ($c eq ')') { $stack_point++ };

        if ($stack_point == 1) {
              $stack_point = 0;
            if($begin_paragraph == 1){
                if($temp_str =~ /^(\w+)\s*=.*$/){
                    $name = $1;
                    printf("%-15s", $name);
                    $begin_paragraph = 0;
                }
                
            }
            
            if($temp_str =~ /HOST\s*=\s*([\d\.]+)\)/){
                $host = $1;
                printf("%-20s", $host);
            }
            
            if($temp_str =~ /PORT\s*=\s*(\d+)\)/){
                  $port = $1;
                  printf("%-10s", $port);
            }
            
            if($temp_str =~ /SERVICE_NAME\s*=\s*(\S+)\s*\)/){
                $service_name = $1;
                printf("%-20s\n", $service_name);
                $begin_paragraph = 1;
            }
            $temp_str='';
        }
    }
}

close(FILE);

哪位朋友看看,是不是还有改进的余地!
if($temp_str =~ /^(\w+)\s*=.*$/){
  $name = $1;
  printf("%-15s", $name);
  $begin_paragraph = 0;
}
上面的代码是否还能改进?
是不是有更好的方式给$name赋值?
其实呢,这个还是有个问题的,
因为HOST= 还可以写主机名的。
所以呢也有要考虑这块的。
借用redspider大哥的代码,用堆栈...

#!/usr/bin/perl


use strict;

my (@head,@data);
my $stack_point = -1;

open(FILE, 'data.txt') or die $!;

while (<FILE>) {
    my @characters = split(//);

    for my $c (@characters) {

        # 忽略空格或换行, 便于后面匹配
        push(@data, $c) if ($c !~ /\s/);

        push(@head, $c) if ($stack_point == -1 and $c !~ /\s/);

        if ($c eq '(') { $stack_point++ }
        elsif ($c eq ')') { $stack_point-- }

        # $stack_point 为 0, 且 @head 有数据,表示读完一个记录头
        if ($stack_point == 0 and @head) {
            my $header = join('',@head);
            $header =~ s/=.*$//;
            print "$header\t";
            @head = (); # 清空头
        }

         # $stack_point 计数为 -1 说明记录的数据读完
        if ($stack_point == -1) {

            my $line = join('',@data);

            # 匹配并提取指定信息

            if ($line =~ /HOST=(\S+)\)\(PORT=(\w+)\).*SERVICE_NAME=(\w+)\)/) {
                print "$1 $2 $3\n";
            }
            @data = (); # 清空数据

        }
    }
}
close FILE;


请各位指教..