【问题标题】:Perl script search/replace and transform resultsPerl 脚本搜索/替换和转换结果
【发布时间】:2016-05-28 16:51:40
【问题描述】:

我正在运行一个简单的 Perl 脚本,它将所有以 \txt 开头的行复制到 \xtx。到目前为止,一切都很好。

use strict;
use warnings;    

$^I = '.bak';

while ( <> ) {

   s/(\\txt )(.*)/$1$2\n\\xtx $2/g;

   print; 
}

现在我想“清理”所有以\\xtx

开头的新行
  1. 删除所有非单词字符:任何非字母但保留带有变音符号的字符

  2. 将所有内容转换为小写。

这就是我的基本编程技能结束的地方

我的文本文件如下所示:

\txt Text (.) with [ symbols and Num[bers (.2) and cháractẽrs with diacrítics  
\abc More text ...

到目前为止,我的脚本产生了:

\txt Text (.) with [ symbols and Num[bers (.2) and cháractẽrs with diacrítics  
\xtx Text (.) with [ symbols and Num[bers (.2) and cháractẽrs with diacrítics  
\abc More text ...

而我想实现:

\txt Text (.) with [ symbols and Num[bers (.2) and cháractẽrs with diacrítics  
\xtx text with symbols and numbers and cháractẽrs with diacrítics  
\abc More text ...

非常感谢任何帮助!

编辑:
这是一个真实的示例字符串:

\_sh v3.0  400  Text3  

\ref 2013-05-01_08.36.14 001  
\txt Djawy (.) de osẽ[ma (.2) EDJu::  
\fts Te equivocaste, saliste,   
\fte   

\ELANParticipant #TBGD  
\ELANBegin 00:00:05.367  
\ELANEnd 00:00:06.521  
\dt 26/May/2016  

\ref 2013-05-01_08.36.14 002  
\txt [A;;;;;;;;;;;;;   
\fts A;;;;;;;;;;;;;  
\fte   
...

... 一切都应该保持原样,除了以 \txt ... 开头的行...

【问题讨论】:

  • duplicates all lines starting with \txt = s/^(\\txt )(.*)/$1$2\n\\xtx $2/mg
  • 您需要s///eg eval 表单来执行此操作。通过空格保留/缩小格式会有点乏味,但可行。
  • 您能否提供真实的示例字符串,因为我认为您的描述不是很清楚。
  • @CasimiretHippolyte 我刚刚用一些真实数据编辑了这个问题。

标签: regex perl


【解决方案1】:

你可以试试这个转换

Perl

use strict;
use warnings;

binmode (DATA, ":utf8");
binmode (STDOUT, ":utf8");

while (<DATA>) {
   s/^(\\txt )(.*)/GetConvetedLine($1,$2)/me;
   print; 
}

sub GetConvetedLine
{
    my ($txt, $body) = @_;
    my $newbody = $body;
    $newbody =~ s/[^\pL\s]+//g;
    $newbody =~ s/\s+/ /g;
    $newbody = lc($newbody);
    return $txt . $body . "\n" . "\\xtx " . $newbody;
}


__DATA__    
\txt Text (.) with [ symbols and Num[bers (.2) and cháractẽrs with diacrítics

输出

\txt Text (.) with [ symbols and Num[bers (.2) and cháractẽrs with diacrítics
\xtx text with symbols and numbers and cháractẽrs with diacrítics

【讨论】:

  • 谢谢!,这看起来会成功!您介意解释一下我如何将其输出到print 到原始文件的输出(如在原始示例中?)所以我可以说perl script.pl myfile.txt 对不起,如果这应该很明显,但我是一个完全的初学者在 perl :/
  • "...寻找的人会找到..." – 我想我想通了...我把我最终使用的代码放在下面,当你有机会时如果我犯了大错,你介意快速检查一下吗? (它确实产生了正确的输出,所以我想一切都很好)非常感谢您的帮助!
【解决方案2】:

你可以稍微重构一下,所以你不必把它全部放在一个正则表达式中:

use strict;
use warnings;    
$^I = '.bak';
while (<>) {
    print; 
    if(/^\\txt/) {
        s/^\\txt//; # remove \txt
        s/[\[\]\(\)//g; # remove all unwanted characters
        print "\xtx $_";
    }
    print; 
}

【讨论】:

  • 感谢您对此进行调查!但是这个脚本也复制了所有其他行。而且我也无法删除符号字符。
【解决方案3】:

为了记录,这是我最终使用的上述 sln 答案的(稍作修改)版本。它可以像我用perl script.pl myfile.txt调用原始脚本一样被调用:

#!/usr/bin/perl

use strict;
use warnings;
use open qw(:std :utf8);
$^I = '.bak'; # create a backup copy 

while (<>) {
   s/^(\\txt )(.*)/GetConvetedLine($1,$2)/me;
   print;
}

sub GetConvetedLine
{
    my ($txt, $body) = @_;
    my $newbody = $body;
    $newbody =~ s/[^\pL\s]+//g;
    $newbody =~ s/ \s+/ /g;
    $newbody = lc($newbody);
    return $txt . $body . "\n" . "\\xtx " . $newbody;
}

【讨论】:

  • 是的,看起来没问题。您不需要 GetConvertedLine() 中的打印,我会像原来一样使用 $newbody =~ s/\s+/ /g;\R 表示换行符。基本上,$newbody 中从来没有任何换行符,因为这是来自 (.*) 的匹配,意思是匹配任何 except 换行符。
  • 谢谢@sln。我放了 \R 因为出于某种原因,我会在$newbody 的末尾得到一些奇怪的“Windows”换行符(可能是由于原始文件中的一些回车),然后是下一行(取决于文本编辑器)不再在下一行。 \R 似乎摆脱了它们。但我现在找到了一个更好的解决方案,它正在搜索s/ \s+/ /g;(即\s+ 之前的一个空格)。这样就可以解决问题了。
猜你喜欢
  • 2020-04-29
  • 2019-05-05
  • 1970-01-01
  • 2011-05-04
  • 2019-01-09
  • 1970-01-01
  • 2021-01-31
  • 1970-01-01
  • 2018-08-21
相关资源
最近更新 更多