仅对子字符串进行更改操作

Fel*_*xJN 6 sed awk perl text-processing

START在由模式和标记的部分前后有任何乱码文本的文件中END(每个特定字符串仅出现一次,并且以正确的顺序出现在同一行上)。我只想对START和之间的部分进行一些字符串操作END

\n

输入示例:

\n
aomodi3hriq32| \xc2\xb6\xc2\xb3r 0q93aoiSTART_this_is_to_be_modified_ENDaqsdofuha23uru| \xc2\xb223i ii3uhfia\noawpo3<9"\xc2\xa7 A hSTART_this_also_needs_modification_ENDqa 032/a237(\xc2\xb01Q"\xc2\xa7 >A_this_\nSTART changeme ENDnot_this_modias\n
Run Code Online (Sandbox Code Playgroud)\n

就 - 操作而言,和sed之间的子字符串(并且仅是子字符串)应该像我使用 一样进行修改。STARTENDsed 's/_this_// ; s/modi/MODI/ ; y/as/45/'

\n

输出示例:

\n
aomodi3hriq32| \xc2\xb6\xc2\xb3r 0q93aoiSTARTi5_to_be_MODIfied_ENDaqsdofuha23uru| \xc2\xb223i ii3uhfia\noawpo3<9"\xc2\xa7 A hSTART4l5o_need5_MODIfic4tion_ENDqa 032/a237(\xc2\xb01Q"\xc2\xa7 >A_this_\nSTART ch4ngeme ENDnot_this_modias\n
Run Code Online (Sandbox Code Playgroud)\n

awkwithFS="START|END"失败,因为OFS不能在不同位置设置多个值。

\n

我尝试使用sed嵌套命令替换和不同的分隔符 ( ) 但失败了,并且还担心之前/之后~可能有字符会扰乱命令(例如 a )。我们的想法是仅选择“内部”子字符串并执行操作,然后将其用作替换的一部分:STARTEND/

\n
sed "s/^\\(.*\\)START.*END\\(.*\\)$/\\1$(sed 's~^.*START~~\n                                         s~END.*~~\n                                         s~_this_~~\n                                         s~modi~MODI~\n                                         y~as~45~' infile)\\2/" infile\n
Run Code Online (Sandbox Code Playgroud)\n

我不熟悉例如perl....但无论如何。

\n

有没有办法使一组sed- 操作仅应用于行的 REGEX 匹配子字符串?

\n

cho*_*oba 5

perl -CSD -ne '
    if (my ($before, $between, $after) = /^(.*START)(.*)(END.*)/) {
        s/_this_//, s/modi/MODI/, tr/as/45/ for $between;
        print "$before$between$after\n";
    } else { print; }' -- file
Run Code Online (Sandbox Code Playgroud)
  • -CSD将输入从 UTF-8 解码并将输出编码为 UTF-8
  • 我们可以使用and来代替填充三个变量$before, $between, 和,但我没有找到更好的解决方案: $after/p${^PREMATCH}${^POSTMATCH}
    if (my ($s) = /START(.*)END/p) {
        s/_this_//, s/modi/MODI/, tr/as/45/ for $s;
        print "${^PREMATCH}START${s}END${^POSTMATCH}";
    } else { print; }
    
    Run Code Online (Sandbox Code Playgroud)

如果 START...END 部分可以在一行上重复,则需要循环每一行。

perl -CSD -ne '
    if (my ($before, $between, $after) = /^(.*START)(.*)(END.*)/) {
        s/_this_//, s/modi/MODI/, tr/as/45/ for $between;
        print "$before$between$after\n";
    } else { print; }' -- file
Run Code Online (Sandbox Code Playgroud)