如何在一行上打印某些起始行和终止行之间的所有内容?
while(<FILE>)
{
chomp $_;
$line[$i]=$_;
++$i;
}
for($j=0;$j<$i;++$j)
{
if($line[$j]=~/Syn_Name/)
{
do
{
print OUT $line[$j],"\n";
++$j;
}
until($line[$j]=~/^\s*$/)
}
}
这是我的代码,我试图打印 Syn_Name 和空行之间的数据。 我的代码提取了我需要的块。 但块之间的数据是逐行打印的。我希望每个块的数据打印在一行上。
while(<FILE>)
{
chomp $_;
$line[$i]=$_;
++$i;
}
for($j=0;$j<$i;++$j)
{
if($line[$j]=~/Syn_Name/)
{
do
{
print OUT $line[$j],"\n";
++$j;
}
until($line[$j]=~/^\s*$/)
}
}
This is my code I am trying to print data between Syn_Name and a blank line.
My code extracts the chunk that I need.
But the data between the chunk is printed line by line. I want the data for each chunk to get printed on a single line.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
简化您的代码。使用触发器操作符来控制打印。请注意,打印最后一行不会添加换行符(除非该行包含多个换行符)。最好的情况是,它打印空字符串。最坏的情况是,它会打印空格。
您不需要线条的转换数组,可以使用 while 循环。如果您无论如何都想存储这些行,我添加了一条注释行,说明了如何最好地完成此操作。
Simplification of your code. Using the flip-flop operator to control the print. Note that printing the final line will not add a newline (unless the line contained more than one newline). At best, it prints the empty string. At worst, it prints whitespace.
You do not need a transition array for the lines, you can use a while loop. In case you want to store the lines anyway, I added a commented line with how that is best done.
目录
Idiomatic Perl
您似乎有 C 系列语言的背景。这很好,因为它可以完成工作,但您可以让 Perl 为您处理机器,即
$_
(对于许多其他 Perl 运算符也是如此)push
将一个元素添加到数组末尾以简化您的第一个循环:
现在您无需更新
$i
跟踪您已经添加到数组中的行数。在第二个循环中,不使用 C 样式
for
循环,而是使用foreach
循环:这样,Perl 就会为您处理簿记工作。
使错误更容易修复
有时 Perl 可能太包容了。假设在第二个循环中您犯了一个简单的印刷错误:
运行您的程序现在根本不会产生任何输出,即使输入包含 Syn_Name 块。
人们可以查看代码并发现您可能打算处理刚刚创建的数组并错误地将数组名称复数化。 Perl 急于提供帮助,创建了一个新的空
@lines
数组,这使得您的foreach
循环无事可做。您可以删除数组名称末尾的虚假
s
,但程序仍然不产生任何输出!例如,您可能有未处理的输入组合,无法打开OUT
文件句柄。Perl 有一些简单的方法可以让您避免因处理无声故障而遭受这些(以及更多!)的挫败感。
有关常见编程错误的警告
您可以打开大量警告列表来帮助诊断常见编程问题。通过我想象的代码的错误版本,Perl 可以告诉您
,并且在修复数组名称中的拼写错误后
,您会立即看到有价值的信息,这些信息可能很难或至少是单调乏味地独立发现:
除非变量名一致,否则不要执行
请注意,即使存在上述潜在问题,Perl 仍会尝试执行。对于某些类型的问题(例如变量命名不一致),您可能希望 Perl 不执行您的程序,而是停下来让您先修复它。你可以告诉 Perl 严格对待变量:
权衡是您必须明确哪些变量您打算成为程序的一部分,而不是让它们在第一次使用时方便地发挥作用。在第一个循环之前,您需要声明
表达您的意图。然后,由于错误地复数数组名称的错误,Perl 失败,
并且您确切地知道哪一行包含错误。
养成这个习惯会为你节省很多时间。
我几乎开始编写每一个重要的 Perl 程序。
第一个是 shebang 行,就 Perl 而言是一个普通的注释。
use
行启用strict
编译指示和警告
编译指示。不想成为一个严格僵尸,如马克Dominus 斥责,我会指出
use strict;
如上所述,不带任何选项使得 Perl 严格处理三个容易出错的区域:这是一个非常有用的默认值。有关更多详细信息,请参阅
strict
pragma 文档。Perl 的范围运算符
perlop 文档 描述了
..
,Perl 的范围运算符,可以帮助您大大简化第二个循环中的逻辑:在你的问题中,你写道你想要“Syn_Name 和空行之间的数据”,在 Perl 中拼写
为在你的情况下,你还想在范围末尾做一些特殊的事情,并且
.. 也提供了这种情况,同上。
分配从
..
返回的值(我通常对名为$inside
或$is_inside
的标量执行此操作)允许您检查是否“ re 在末尾,例如,以这种方式编写还可以避免重复终止条件的代码(
..
的右侧操作数)。这样,如果您需要更改逻辑,只需在一处更改即可。当您必须记住时,有时您会忘记并产生错误。工作演示
请参阅下面的代码,您可以复制并粘贴以获得工作程序。出于演示目的,它们从内置
DATA
文件句柄读取输入并将输出写入STDOUT
。以这种方式编写意味着您可以将我的代码转移到您的代码中,而无需进行很少的修改或无需修改。立即打印 chomped 行
正如您的问题中所定义的,不需要一个循环来收集临时数组中的行,然后另一个循环来处理该数组。考虑以下代码,
其输出为“
我们总是打印当前行,存储在
$_
”中。当我们到达范围的末尾时,即当$is_last
为 true 时,我们还会打印换行符。当 $is_last 为 false 时,三元运算符另一个分支中的空列表就是结果,这意味着我们仅打印$_
,不打印换行符。用空格连接行
您没有向我们展示示例输入,所以我想知道您是否真的想将这些行连接在一起而不是 用空格连接它们。如果您想要后一种行为,则程序将变为
此代码仅在 Syn_Name 块内的那些行中累积@lines,打印该块,并在我们执行时清除@lines。看到终结者。现在的输出是
另一种边缘情况
最后,如果我们在文件末尾看到 Syn_Name 但没有终止空行,会发生什么情况?对于您的数据来说这可能是不可能的,但如果您需要处理它,您将需要使用 Perl 的
eof
运算符。因此,我们在空行或文件末尾处终止。
输出:
这里代码删除了所有尾随的内容,而不是
chomp
行尾不可见的空白。即使输入有点马虎,这也将确保连接线之间的间距是均匀的。如果没有
eof
检查,程序不会打印后一行,您可以通过注释掉活动条件并取消注释另一行来看到这一点。Contents
Idiomatic Perl
You seem to have a background with the C family of languages. This is fine because it gets the job done, but you can let Perl handle the machinery for you, namely
chomp
defaults to$_
(also true with many other Perl operators)push
adds an element to the end of an arrayto simplify your first loop:
Now you don't have update
$i
to keep track of how many lines you've already added to the array.On the second loop, instead of using a C-style
for
loop, use aforeach
loop:This way, Perl handles the bookkeeping for you.
Make errors easier to fix
Sometimes Perl can be too accommodating. Say in the second loop you made an easy typographical error:
Running your program now produces no output at all, even if the input contains Syn_Name chunks.
A human can look at the code and see that you probably intended to process the array you just created and pluralized the name of the array by mistake. Perl, being eager to help, creates a new empty
@lines
array, which leaves yourforeach
loop with nothing to do.You may delete the spurious
s
at the end of the array's name but still have a program produces no output! For example, you may have an unhandled combination of inputs that doesn't open theOUT
filehandle.Perl has a couple of easy ways to spare you these (and more!) kinds of frustration from dealing with silent failures.
Warnings about common programming errors
You can turn on an enormous list of warnings that help diagnose common programming problems. With my imagined buggy version of your code, Perl could have told you
and after fixing the typo in the array name
Right away, you see valuable information that may be difficult or at least tedious to spot unaided:
Don't execute unless variable names are consistent
Notice that even with the potential problems above, Perl tried to execute anyway. With some classes of problems such as the variable-naming inconsistency, you may prefer that Perl not execute your program but stop and make you fix it first. You can tell Perl to be strict about variables:
The tradeoff is you have to be explicit about which variables you intend to be part of your program instead of allowing them to conveniently spring to life upon first use. Before the first loop, you would declare
to express your intent. Then with the bug of a mistakenly pluralized array name, Perl fails with
and you know exactly which line contains the error.
Developing this habit will save you lots of time
I begin almost every non-trivial Perl program I write with
The first is the shebang line, an ordinary comment as far as Perl is concerned. The
use
lines enable thestrict
pragma and thewarnings
pragma.Not wanting to be a strict-zombie, as Mark Dominus chided, I'll point out that
use strict;
as above with no option makes Perl strict in dealing with three error-prone areas:This is a highly useful default. See the
strict
pragma's documentation for more details.Perl's range operator
The perlop documentation describes
..
, Perl's range operator, that can help you greatly simplify the logic in your second loop:In your question, you wrote that you want “data between Syn_Name and a blank line,” which in Perl is spelled
In your case, you also want to do something special at the end of the range, and
..
provides for that case too, ibid.Assigning the value returned from
..
(which I usually do to a scalar named$inside
or$is_inside
) allows you to check whether you're at the end, e.g.,Writing it this way also avoids duplicating the code for your terminating condition (the right-hand operand of
..
). This way if you need to change the logic, you change it in only one place. When you have to remember, you'll forget sometimes and create bugs.Working demos
See below for code you can copy-and-paste to get working programs. For demo purposes, they read input from the built-in
DATA
filehandle and write output toSTDOUT
. Writing it this way means you can transfer my code into yours with little or no modification.Print chomped lines immediately
As defined in your question, there's no need for one loop to collect the lines in a temporary array and then another loop to process the array. Consider the following code
whose output is
We always print the current line, stored in
$_
. When we're at the end of the range, that is, when$is_last
is true, we also print a newline. When$is_last
is false, the empty list in the other branch of the ternary operator is the result—meaning we print$_
only, no newline.Join lines with spaces
You didn't show us an example input, so I wonder whether you really want to butt the lines together rather than joining them with spaces. If you want the latter behavior, then the program becomes
This code accumulates in
@lines
only those lines within a Syn_Name chunk, prints the chunk, and clears out@lines
when we see the terminator. The output is nowOne more edge case
Finally, what happens if we see Syn_Name at the end of the file but without a terminating blank line? That may be impossible with your data, but in case you need to handle it, you'll want to use Perl's
eof
operator.So we terminate on either a blank line or end of file.
Output:
Here instead of
chomp
, the code removes any trailing invisible whitespace at the ends of lines. This will make sure spacing between joined lines is uniform even if the input is a little sloppy.Without the
eof
check, the program does not print the latter line, which you can see by commenting out the active conditional and uncommenting the other.另一个简化版本:
Another simplified version: