perl从文件中删除字符串块并保存到文件 [英] perl remove string block from file and save to file
问题描述
我有一个看起来像这样的文件:
字符串1 {abc {会话1}合理的价格 {编号LU0432618274456来源4服务xyz}}字符串2 {abc {会话23}合理的价格 {ID LU036524565456171来源4慈济}}
我的程序应读取具有给定搜索参数(例如字符串1")的文件,并搜索整个块,直到}"为止,然后从文件中删除该部分.有人可以帮忙...到目前为止,我有一些代码,但是我该如何删除并再次保存到同一文件?
my $ fh = IO :: File-> new("$ fname","r")或死亡(错误:未找到策略文件\" $ fname \.");while($ line =< $ fh>){如果($ line =〜/^ \ s * string 1 \ s * \ w + \ s * \ {\ s * $/){$ inside_json_msg = 1;$ msg_json.= $ line;}别的 {如果($ inside_json_msg){如果($ line =〜m/^ \} \ s * $/){$ msg_json.= $ line如果已定义($ line);$ inside_json_msg = 0;} 别的 {$ msg_json.= $ line;}}}}
您的代码提到了JSON,但您的数据不是JSON.如果它是JSON,而您转录得很糟糕,请使用一个JSON库.>
但是,如果您的数据不是JSON,则可以执行以下操作.
#!/usr/bin/perl使用严格使用警告;my $ match = shift或die我需要一个字符串来匹配\ n";while(< DATA>){#如果这是一个块的开始,我们要删除...如果(/^ \ s * $ match \ s + {/){#将$ braces设置为1(如果该行在此行关闭,则设置为0)我的$大括号=/}/吗?0:1;#虽然$大括号为非零while($大括号){#读取文件的下一行$ _ =< DATA> ;;#适当地增加或减少$大括号$大括号-如果/}/;$大括号++,如果/{/;}} 别的 {#否则,只打印行打印;}}__数据__字符串1 {abc {会话1}合理的价格 {编号LU0432618274456来源4服务xyz}}字符串2 {abc {会话23}合理的价格 {ID LU036524565456171来源4慈济}}
当前,这只是将输出打印到控制台.我使用 DATA
文件句柄进行更轻松的测试.留给读者练习是使用真实的文件句柄:-)
更新:我认为我不喜欢使用正则表达式匹配 $ braces
的所有增量和减量.因此,这是另一个(改进的?)版本,它使用 y/.../.../
来计算行中右括号和右括号的出现次数.此版本的可读性可能会稍差(语法突出显示工具肯定会这样认为).
#!/usr/bin/perl使用严格使用警告;my $ match = shift或die我需要一个字符串来匹配\ n";while(< DATA>){如果(/^ \ s * $ match \ s + {/){我的$大括号= y/{//-y/}//;while($大括号){$ _ =< DATA> ;;$大括号-= y/}//;$大括号+ = y/{//;}} 别的 {打印;}}__数据__字符串1 {abc {会话1}合理的价格 {编号LU0432618274456来源4服务xyz}}字符串2 {abc {会话23}合理的价格 {ID LU036524565456171来源4慈济}}
更新2:好吧,我最初说的是,处理真正的文件句柄将留给读者练习.但这是一个执行此操作的版本.
#!/usr/bin/perl使用严格使用警告;my $ match = shift或die我需要一个字符串来匹配\ n";打开我的$ fh,'+<','data'或死亡$ !;#读取文件中的所有数据我的@data =< $ fh> ;;#清空文件寻求$ fh,0,0;截断$ fh,0;我的$ x = 0;而($ x< = $#data){$ _ = $ data [$ x ++];如果(/^ \ s * $ match \ s + {/){我的$大括号= y/{//-y/}//;while($大括号){$ _ = $ data [$ x ++];$大括号-= y/}//;$大括号+ = y/{//;}} 别的 {打印$ fh $ _;}}
当前,我已经将文件名硬编码为 data
.我希望很明显如何解决该问题.
I have a file that looks like this:
string 1 {
abc { session 1 }
fairPrice {
ID LU0432618274456
Source 4
service xyz
}
}
string 2 {
abc { session 23 }
fairPrice {
ID LU036524565456171
Source 4
service tzu
}
}
My program should read in the file with a search-parameter given (for example "string 1") and search the complete block until "}" and remove that part from the file. Can someone assist on that...I have some code so far but how can I do the removal and saving to the same file again?
my $fh = IO::File->new( "$fname", "r" ) or die ( "ERROR: Strategy file \"$fname\" not found." );
while($line=<$fh>)
{
if ($line =~ /^\s*string 1\s*\w+\s*\{\s*$/) {
$inside_json_msg = 1;
$msg_json .= $line;
}
else {
if ($inside_json_msg)
{
if ($line =~ m/^\}\s*$/) {
$msg_json.= $line if defined($line);
$inside_json_msg = 0;
} else {
$msg_json .= $line;
}
}
}
}
You code mentions JSON, but your data isn't JSON. If it is JSON and you've just transcribed it badly, then please use a JSON library.
But if your data isn't JSON, then something like this will do the trick.
#!/usr/bin/perl
use strict;
use warnings;
my $match = shift or die "I need a string to match\n";
while (<DATA>) {
# If this is the start of a block we want to remove...
if (/^\s*$match\s+{/) {
# Set $braces to 1 (or 0 if the block closes on this line)
my $braces = /}/ ? 0 : 1;
# While $braces is non-zero
while ($braces) {
# Read the next line of the file
$_ = <DATA>;
# Increment or decrement $braces as appropriate
$braces-- if /}/;
$braces++ if /{/;
}
} else {
# Otherwise, just print the line
print;
}
}
__DATA__
string 1 {
abc { session 1 }
fairPrice {
ID LU0432618274456
Source 4
service xyz
}
}
string 2 {
abc { session 23 }
fairPrice {
ID LU036524565456171
Source 4
service tzu
}
}
Currently, this just prints the output to the console. And I use the DATA
filehandle for easier testing. Switching to use real filehandles is left as an exercise for the reader :-)
Update: I decided that I didn't like all the incrementing and decrementing of $braces
using regex matches. So here's another (improved?) version that uses y/.../.../
to count the occurrences of opening and closing braces in the line. It's possible that this version might be slightly less readable (the syntax highlighter certainly thinks so).
#!/usr/bin/perl
use strict;
use warnings;
my $match = shift or die "I need a string to match\n";
while (<DATA>) {
if (/^\s*$match\s+{/) {
my $braces = y/{// - y/}//;
while ($braces) {
$_ = <DATA>;
$braces -= y/}//;
$braces += y/{//;
}
} else {
print;
}
}
__DATA__
string 1 {
abc { session 1 }
fairPrice {
ID LU0432618274456
Source 4
service xyz
}
}
string 2 {
abc { session 23 }
fairPrice {
ID LU036524565456171
Source 4
service tzu
}
}
Update 2: Ok, I originally said that dealing with real filehandles would be left as an exercise for the reader. But here's a version that does that.
#!/usr/bin/perl
use strict;
use warnings;
my $match = shift or die "I need a string to match\n";
open my $fh, '+<', 'data' or die $!;
# Read all the data from the file
my @data = <$fh>;
# Empty the file
seek $fh, 0, 0;
truncate $fh, 0;
my $x = 0;
while ($x <= $#data) {
$_ = $data[$x++];
if (/^\s*$match\s+{/) {
my $braces = y/{// - y/}//;
while ($braces) {
$_ = $data[$x++];
$braces -= y/}//;
$braces += y/{//;
}
} else {
print $fh $_;
}
}
Currently, I've hard-coded the filename to be data
. I hope it's obvious how to fix that.
这篇关于perl从文件中删除字符串块并保存到文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!