[求助]如何改写文件中特定位置的字符

我在“tie my @arry,'Tie::File', $filename or die "Couldn't tie!\n";”这句话后面加了
print "$arry[0]\n";
getc;
print "$arry[1]\n";
getc;
print "$arry[2]\n";
getc;
看@arry的各元素都是什么,print出来之后发现, print "$arry[0]\n";把整个xml都print出来了print "$arry[1]\n";和print "$arry[2]\n";都是空的。
这样的话,我以前的$arry[2] ='<!DOCTYPE sub SYSTEM "D:\Data\model.dtd">';这句话是怎么给数组赋值的呢?
明白了,因为$arry[0]取走了文件所有的内容,所以在$arry[1]="..."的赋值操作后,才会出现print到文件末尾的结果;关于数组的下标, Lonki是正确的,我想是cpan的例子可能出现笔误了;而当初我令$arry[2]=“...”之后print到末尾第二行,是因为$arry[1]没有幅值,所以输出空行。
于是新的问题又来了,为什么tie操作之后,整个文件都付给$arry[0]了呢,不是应该每行对应一个元素的么?
我把代码改成这个样子,
my $filename = "D:\\Data\\test.xml";
#open FH, "+<".$filename or die "$!\n";
tie my @arry,'Tie::File',$filename or die "Couldn't tie!\n";

$arry[0] ='<!DOCTYPE bbs SYSTEM "D:\Data\model.dtd">';

untie @arry;
结果整个文件都毁了,只剩下一行:
<!DOCTYPE bbs SYSTEM "D:\Data\model.dtd">

还是不明白怎么回事


QUOTE:
原帖由 ttyuren 于 2007-10-11 21:56 发表
我在“tie my @arry,'Tie::File', $filename or die "Couldn't tie!\n";”这句话后面加了
print "$arry[0]\n";
getc;
print "$arry[1]\n";
getc;
print "$arry[2]\n";
getc;
看@arry的各元素都是什么,p ...



QUOTE:
"为什么tie操作之后,整个文件都付给$arry[0]了呢"

你中间的getc......

这样看:
tie my @arry,'Tie::File', $filename or die "Couldn't tie!\n";
for (0..$#arry) {
    print "$_: $arry[$_]\n";
}

另外:
测试时, 先注掉所有无关代码, 再给$arry某一元素复制, 看结果.

嗯,照做了,而且我用print $#arry;看了@arry数组元素的个数,输出是0;也就是说,还不是按行tie的,而是把整个文件都付给$arry[0]了。真奇怪。

终于找到原因了... 我靠...


你在Win上对吧?

ActivePerl的Tie::File来处理Unix文本格式文件(即"\n"分隔), 那么会将整个文件当作[0];
因此请将待处理的文本文件转换成DOS格式先("\r\n"分隔).

### unix2dos

use strict;
use warnings;
use Tie::File;

tie my @lines, 'Tie::File', $ARGV[0] or die "Cannot open $ARGV[0]: $!\n";

map { $_ =~ s/\n/"\r\n"/eg; } @lines;

untie @lines;




QUOTE:
原帖由 Lonki 于 2007-10-11 22:46 发表
终于找到原因了... 我靠...


你在Win上对吧?

ActivePerl的Tie::File来处理Unix文本格式文件(即"\n"分隔), 那么会将整个文件当作[0];
因此请将待处理的文本文件转换成DOS格式先("\r\n"分隔).

### uni ...

谢谢Lonki!!
在你的提示下我又把Tie::File好好看了一遍,的确有这个说明啊!(真粗心~)
在Tie::File中有一个选项, recsep(慌张中还把cs敲反了-_-!!)设置为"\n"的话,不用map也是正确的了。
再次感谢Lonki,感谢kgd924和大家!


QUOTE:
原帖由 ttyuren 于 2007-10-11 18:08 发表
我需要从xml文件中提取数据,dtd是模板,因为dtd文件在网上,不如本地取省时间,所以我想把它的目录改一下。改目录不是最终目的,而是调用它来读取xml的数据。我想用XML::LibXML的语法分析器,我也是刚学,好多不懂

在XML::LibXML倒还没有找到映射到本地dtd的办法,而且你的<!DOCTYPE >还定义为SYSTEM. 不过到可以设置一个参数忽略DTD。
local $XML::LibXML::skipDTD = 1;

如果DTD只是定义了文档结构的话忽略是没有的问题。


QUOTE:
原帖由 kgd924 于 2007-10-12 10:01 发表


在XML::LibXML倒还没有找到映射到本地dtd的办法,而且你的还定义为SYSTEM. 不过到可以设置一个参数忽略DTD。
local $XML::LibXML::skipDTD = 1;

如果DTD只是定义了文档结构的话忽略是没有的问题。

我把这一行修改的目的就是想把远程的dtd文件移到本地调用。DTD文件只定义了文档结构,再请问kgd924, 如果不用XML::LibXML的话,用哪个模块怎么实现比较方便呢(DOM?)?更弱弱的问一下,“而且你的还定义为SYSTEM”是什么意思?定义为SYSTEM的dtd处理方式不同么?“不过到可以设置一个参数忽略DTD”,“忽略”又是什么意思呢?
systemId和publicId又是什么呢?