How can I check for the next line while running in a current loop? Also, how can I move C comments to end of the line for a table?
如何在当前循环中运行时检查下一行?另外,如何将C注释移动到表的行尾?
I have a file like this:
我有这样一个文件:
array_table=
{
/* comment 1*/ (unsigned int a);
/* comment 2*/ (unsigned int b);
/* comment 3*/ (unsigned int c);
/* comment 4*/ (unsigned int d);
}
My intention is to move those comments to the end of the line like:
我的意图是将这些评论移到最后一行,如:
array_table=
{
(unsigned int a); /* comment 1*/
(unsigned int b); /* comment 2*/
(unsigned int c); /* comment 3*/
(unsigned int d); /* comment 4*/
}
How can I do that in Perl? Can anyone help me with the Perl code?
我怎么能在Perl中做到这一点?任何人都可以帮助我使用Perl代码吗?
4 个解决方案
#1
Something like this should work:
像这样的东西应该工作:
while (<>) {
chomp;
if ($_ =~ m%^(.*)/\*(.*)\*/(.*)$%) {
printf "%s%s/*%s*/%s", $1, $3, $2, $/;
} else {
print $_ . $/;
}
}
The bracketed expressions match anything before the comment, the comment itself, and anything left after the comment. The printf
then recomposes them in the right order.
括号中的表达式匹配评论之前的任何内容,评论本身以及评论后留下的任何内容。然后printf以正确的顺序重新组合它们。
#2
OK - to restate what I think you are asking for, you want to parse a file, and look for assigments of the form
好的 - 重申我认为你要求的东西,你想解析一个文件,并寻找表格的分配
foo=
{
....
}
and within the block, you want to move the comments to the end of the line. There are a number of ways to do this, the most elegant is usually related to what else you are doing in the loop. The one that springs to mind is just to remember the fact that the last line contained an '=' and use that fact when matching for '{' at the start of a line. Using one of my favourite perl constructs, the range operator in scalar context. So this would give...
在块中,您希望将注释移动到行尾。有很多方法可以做到这一点,最优雅的方法通常与你在循环中做的其他事情有关。浮现在脑海中的那个只是为了记住最后一行包含'='并在一行开头匹配'{'时使用该事实的事实。使用我最喜欢的perl结构之一,标量上下文中的范围运算符。所以这会给......
my $last_line_an_assignment = 0;
while (<DATA>)
{
if (($last_line_an_assignment && m!^\s*{!) .. m!^\s*}!)
{
s!(/\*.*?\*/)\s*(.*)$!$2 $1!;
}
print $_;
$last_line_an_assignment = m!=!;
}
__DATA__
/* comment other */ (unsigned int a);
other_assignment=
/* not a table */ 12;
array_table=
{
/* comment 1*/ (unsigned int a);
/* comment 2*/ (unsigned int b);
/* comment 3*/ (unsigned int c);
/* comment 4*/ (unsigned int d);
}
/* comment other */ (unsigned int a);
You can either print the data to another file, or you can update the files in place, using the '-i' option to perl
您可以将数据打印到另一个文件,也可以使用perl的'-i'选项更新文件
local (@ARGV) = ($filename);
local ($^I) = '.bak';
while (<>)
{
# make changes to line AND call print
}
This causes perl to make a backup of $filename (with extention '.bak'), and then all print calls in the loop will overwrite the contents if the file - for more information see the '-i' option in the "perlrun" manual page.
这会导致perl备份$ filename(扩展名为'.bak'),然后循环中的所有打印调用都将覆盖文件中的内容 - 有关更多信息,请参阅“perlrun”中的'-i'选项手册页。
#3
If you want change only comments inside array_table
statement:
如果您只想更改array_table语句中的注释:
perl -pe's,^(\s*)(/\*.*?\*/)\s*(.*?)[ \t]*$,$1$3 $2, if/^\s*array_table\s*=/../^\s*\}/'
otherwise simply:
perl -pe's,^(\s*)(/\*.*?\*/)\s*(.*?)[ \t]*$,$1$3 $2,'
#4
Use Regexp::Common rather than rolling your own. E.g.
使用Regexp :: Common而不是自己动手。例如。
use Regexp::Common;
while ($_ = <DATA>) {
chomp;
if (s/(^\s*)($RE{comment}{C})//) {
print $1, $_, $2, "\n";
}
else {
print $_, "\n";
}
}
__DATA__
/* comment other */ (unsigned int a);
other_assignment=
/* not a table */ 12;
array_table=
{
/* comment 1*/ (unsigned int a);
/* comment 2*/ (unsigned int b);
/* comment 3*/ (unsigned int c);
/* comment 4*/ (unsigned int d);
}
/* comment other */ (unsigned int a);
#1
Something like this should work:
像这样的东西应该工作:
while (<>) {
chomp;
if ($_ =~ m%^(.*)/\*(.*)\*/(.*)$%) {
printf "%s%s/*%s*/%s", $1, $3, $2, $/;
} else {
print $_ . $/;
}
}
The bracketed expressions match anything before the comment, the comment itself, and anything left after the comment. The printf
then recomposes them in the right order.
括号中的表达式匹配评论之前的任何内容,评论本身以及评论后留下的任何内容。然后printf以正确的顺序重新组合它们。
#2
OK - to restate what I think you are asking for, you want to parse a file, and look for assigments of the form
好的 - 重申我认为你要求的东西,你想解析一个文件,并寻找表格的分配
foo=
{
....
}
and within the block, you want to move the comments to the end of the line. There are a number of ways to do this, the most elegant is usually related to what else you are doing in the loop. The one that springs to mind is just to remember the fact that the last line contained an '=' and use that fact when matching for '{' at the start of a line. Using one of my favourite perl constructs, the range operator in scalar context. So this would give...
在块中,您希望将注释移动到行尾。有很多方法可以做到这一点,最优雅的方法通常与你在循环中做的其他事情有关。浮现在脑海中的那个只是为了记住最后一行包含'='并在一行开头匹配'{'时使用该事实的事实。使用我最喜欢的perl结构之一,标量上下文中的范围运算符。所以这会给......
my $last_line_an_assignment = 0;
while (<DATA>)
{
if (($last_line_an_assignment && m!^\s*{!) .. m!^\s*}!)
{
s!(/\*.*?\*/)\s*(.*)$!$2 $1!;
}
print $_;
$last_line_an_assignment = m!=!;
}
__DATA__
/* comment other */ (unsigned int a);
other_assignment=
/* not a table */ 12;
array_table=
{
/* comment 1*/ (unsigned int a);
/* comment 2*/ (unsigned int b);
/* comment 3*/ (unsigned int c);
/* comment 4*/ (unsigned int d);
}
/* comment other */ (unsigned int a);
You can either print the data to another file, or you can update the files in place, using the '-i' option to perl
您可以将数据打印到另一个文件,也可以使用perl的'-i'选项更新文件
local (@ARGV) = ($filename);
local ($^I) = '.bak';
while (<>)
{
# make changes to line AND call print
}
This causes perl to make a backup of $filename (with extention '.bak'), and then all print calls in the loop will overwrite the contents if the file - for more information see the '-i' option in the "perlrun" manual page.
这会导致perl备份$ filename(扩展名为'.bak'),然后循环中的所有打印调用都将覆盖文件中的内容 - 有关更多信息,请参阅“perlrun”中的'-i'选项手册页。
#3
If you want change only comments inside array_table
statement:
如果您只想更改array_table语句中的注释:
perl -pe's,^(\s*)(/\*.*?\*/)\s*(.*?)[ \t]*$,$1$3 $2, if/^\s*array_table\s*=/../^\s*\}/'
otherwise simply:
perl -pe's,^(\s*)(/\*.*?\*/)\s*(.*?)[ \t]*$,$1$3 $2,'
#4
Use Regexp::Common rather than rolling your own. E.g.
使用Regexp :: Common而不是自己动手。例如。
use Regexp::Common;
while ($_ = <DATA>) {
chomp;
if (s/(^\s*)($RE{comment}{C})//) {
print $1, $_, $2, "\n";
}
else {
print $_, "\n";
}
}
__DATA__
/* comment other */ (unsigned int a);
other_assignment=
/* not a table */ 12;
array_table=
{
/* comment 1*/ (unsigned int a);
/* comment 2*/ (unsigned int b);
/* comment 3*/ (unsigned int c);
/* comment 4*/ (unsigned int d);
}
/* comment other */ (unsigned int a);