首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在Perl中交换两个连续的行?

如何在Perl中交换两个连续的行?
EN

Stack Overflow用户
提问于 2010-05-21 10:45:50
回答 2查看 1.5K关注 0票数 2

我有一段编辑提示表的代码,如果找到了,我不知道如何反转两个连续的行:

代码语言:javascript
复制
/^TITLE.*?"$/  
/^PERFORMER.*?"$/

反转到

代码语言:javascript
复制
/^PERFORMER.*?"$/  
/^TITLE.*?"$/  

在我的情况下,解决方案是什么?

代码语言:javascript
复制
use strict; 
use warnings; 
use File::Find; 
use Tie::File;


my $dir_target = 'test';

find(\&c, $dir_target);        
sub c {  
   /\.cue$/ or return;

   my $fn = $File::Find::name;

   tie my @lines, 'Tie::File', $fn or die "could not tie file: $!"; 
        for (my $i = 0;  $i < @lines; $i++) {
             if ($lines[$i] =~ /^REM (DATE|GENRE|REPLAYGAIN).*?$/) {
                  splice(@lines, $i, 3);
             }
     if ($lines[$i] =~ /^\s+REPLAYGAIN.*?$/) {
                  splice(@lines, $i, 1);
             }
        }

   untie @lines; 
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2010-05-21 12:05:50

好的,因为您绑定到一个数组中,所以我只检查$lines[$i]$lines[$i+1] (只要+1地址存在),如果前者与标题匹配,而后者与表演者匹配,则交换它们。除非您可能需要转置这些,即使它们不是连续的??

如果你知道它们是连续的,这里有一个选项(这段代码将放在你的for循环中,也许在REM检查行的上面):

代码语言:javascript
复制
if ($i < $#lines and $lines[$i] =~ /^TITLE.*?"$/
                 and $lines[$i+1] =~ /^PERFORMER.*?$/) {
    my $tmp = $lines[$i];
    $lines[$i] = $lines[$i+1];
    $lines[$i+1] = $tmp;
}

另一种选择(无论是否连续都可以工作,而且可以说更优雅)将是

代码语言:javascript
复制
use List::MoreUtils qw(first_index);

(在顶部,使用其他use语句),然后执行(在&c内,但在for循环之外):

代码语言:javascript
复制
my $title_idx = first_index { /^TITLE.*?"$/ } @lines;
my $performer_idx = first_index { /^PERFORMER.*?"$/ } @lines;

if($title_idx >= 0 and $performer_idx >= 0 and $title_idx < $performer_idx)
{
    # swap these lines:
    ($lines[$title_idx],$lines[$performer_idx]) =
        ($lines[$performer_idx],$lines[$title_idx]);
}

这就是你要找的吗?

票数 0
EN

Stack Overflow用户

发布于 2010-05-21 12:01:28

这可能看起来有点夸张,但是看到您的文件不是很大,我很想利用以下一行代码(从命令行或通过system调用)。

一行程序的工作原理是一次遍历所有行,然后将其余的工作留给一个正则表达式替换,该替换颠倒了行的顺序。

如果你使用*nix:

代码语言:javascript
复制
perl -0777 -i -ne 's/(TITLE.*?")\n(PERFORMER.*?")/$2\n$1/g' file1 file2 ..

如果您使用的是Windows,则需要创建现有文件的备份:

代码语言:javascript
复制
perl -0777 -i.bak -ne "s/(TITLE.*?\")\n(PERFORMER.*?\")/$2\n$1/g" file1 file2 ..

解释

命令开关(有关详细信息,请参阅perlrun )

骰子(一个八进制数)强制执行文件窃取,behavior

  • -i启用就地编辑(不需要splice-‘n’-
  • -0777!)。Windows系统要求您提供一个备份扩展名,因此会在文件中的所有行上执行额外的.bak
  • -n循环(尽管由于您是在窃听它们,所以Perl将每个文件的内容视为一个line)
  • -e,从而允许Perl识别command-line

中的代码

正则表达式

  • 替换正则表达式捕获所有出现的TITLE行,即连续的PERFORMER行,并将其分别存储在变量$1$2中。然后,替换正则表达式颠倒两个变量的顺序,用换行符分隔。

文件名参数

  • 您可以使用*nix来提供有问题的目录的文件名,但我会让其他人来解决这个问题,因为我现在还不太熟悉Unix管道(有关更多指导,请参阅此John Siracusa answer )。

在你尝试这些一行程序之前,我会为你的文件创建一个备份。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2879274

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档