Regex mutliline正则表达式串联

Regex mutliline正则表达式串联,regex,perl,awk,sed,grep,Regex,Perl,Awk,Sed,Grep,我在这里遇到了一个棘手的问题,我正在努力解决。它涉及多行搜索替换和/或连接情况。 这是我的输入文本: // import tset flash_read, flash_writ; vector ( $tset , (XMOSI, XMISO, XSCLK, XSTRMSTR

我在这里遇到了一个棘手的问题,我正在努力解决。它涉及多行搜索替换和/或连接情况。 这是我的输入文本:

//                                                                                                            
import tset flash_read, flash_writ;
vector  ( $tset     , (XMOSI, XMISO, XSCLK, XSTRMSTRT, XSTRMSCLK, XSTRMCKEN, XXTALIN, XXTALCPUEN, XHVREGON, XFDRESET, XGLDATA5, XGLDATA4, XGLDATA3, XGLDATA2, XGLDATA1, XGLDATA0):H, (XSTRMD3, XSTRMD2, XSTRMD1, XSTRMD0, XNSS3, XNSS2, XNSS1, XNSS0):H, XTECLOCK, XRXDATA, XRXENABLE, XTXDATA, XTXENABLE, XNRESET, XTCK, XTMS, XTDI, XTDO, XNTRST)
{
repeat 2 
 > flash_writ X0X00X0XXXXXXXXX 0000XXXX X 0 L X X 0 1 0 0 X 0; // XNTRST
repeat 9 
 > flash_writ X0X00X0XXXXXXXXX 0000XXXX X 0 L X X 0 1 1 0 X 1; // Test Logic Reset
 > flash_writ X0X00X0XXXXXXXXX 0000XXXX X 0 L X X 0 1 0 0 X 1; // Run Test Idle
repeat 2 
 > flash_writ X0X00X0XXXXXXXXX 0000XXXX X 0 L X X 0 1 1 0 X 1; // Select IR
我想要的输出格式如下:

//                                                                                                            
import tset flash_read, flash_writ;
vector  ( $tset     , (XMOSI, XMISO, XSCLK, XSTRMSTRT, XSTRMSCLK, XSTRMCKEN, XXTALIN, XXTALCPUEN, XHVREGON, XFDRESET, XGLDATA5, XGLDATA4, XGLDATA3, XGLDATA2, XGLDATA1, XGLDATA0):H, (XSTRMD3, XSTRMD2, XSTRMD1, XSTRMD0, XNSS3, XNSS2, XNSS1, XNSS0):H, XTECLOCK, XRXDATA, XRXENABLE, XTXDATA, XTXENABLE, XNRESET, XTCK, XTMS, XTDI, XTDO, XNTRST)
{
repeat 2              > flash_writ X0X00X0XXXXXXXXX 0000XXXX X 0 L X X 0 1 0 0 X 0; // XNTRST
repeat 9              > flash_writ X0X00X0XXXXXXXXX 0000XXXX X 0 L X X 0 1 1 0 X 1; // Test Logic Reset
                      > flash_writ X0X00X0XXXXXXXXX 0000XXXX X 0 L X X 0 1 0 0 X 1; // Run Test Idle
repeat 2              > flash_writ X0X00X0XXXXXXXXX 0000XXXX X 0 L X X 0 1 1 0 X 1; // Select IR 
我正在寻找一个unix one liner,它将搜索输入文本中包含repeat的行,并用空格替换repeat count末尾的新行字符,以便最终结果看起来像是将repeat行与其下一行连接在一起,如输出文本中所示,带有指定数量的空格

对于不包含重复计数的行,只需将行的开头按输出文本中所示的空格数

我已经探索了一些领域来实现这一点,但是没有完成 (1) 使用分支标签、N、模式空间进行Sed (2) AWK与改变RS (3) 启用s///和多行标志的Perl

假设这可以通过一个成熟的perl或python脚本中的嵌套regex if条件来实现,但我正在寻找一个更优雅的解决方案

perl
中:

perl -0777 -lne 's/^(repeat[ ]+\d+)\s+/\1\t/mg; s/^[ ]*>/\t\t>/mg; print' file 
//                                                                                                            
import tset flash_read, flash_writ;
vector  (      , (XMOSI, XMISO, XSCLK, XSTRMSTRT, XSTRMSCLK, XSTRMCKEN, XXTALIN, XXTALCPUEN, XHVREGON, XFDRESET, XGLDATA5, XGLDATA4, XGLDATA3, XGLDATA2, XGLDATA1, XGLDATA0):H, (XSTRMD3, XSTRMD2, XSTRMD1, XSTRMD0, XNSS3, XNSS2, XNSS1, XNSS0):H, XTECLOCK, XRXDATA, XRXENABLE, XTXDATA, XTXENABLE, XNRESET, XTCK, XTMS, XTDI, XTDO, XNTRST)
{
repeat 2    > flash_writ X0X00X0XXXXXXXXX 0000XXXX X 0 L X X 0 1 0 0 X 0; // XNTRST
repeat 9    > flash_writ X0X00X0XXXXXXXXX 0000XXXX X 0 L X X 0 1 1 0 X 1; // Test Logic Reset
            > flash_writ X0X00X0XXXXXXXXX 0000XXXX X 0 L X X 0 1 0 0 X 1; // Run Test Idle
repeat 2    > flash_writ X0X00X0XXXXXXXXX 0000XXXX X 0 L X X 0 1 1 0 X 1; // Select IR
perl -lne ' if (/^repeat[\h]+\d+/) {$ll=$_; next} 
            if (/^\h+>/) {$_=sprintf("%-21s%s",$ll,$_);$ll="";}
            print' file
或者,您也可以执行以下操作:

perl -0777 -lpe 's/^(repeat[ ]+\d+)\s+/\1\t/mg; s/^[ ]*>/\t\t>/mg;' file
在第二次换人中,你可能需要考虑有多少个
\t
,但你知道了


Ed的awk非常出色。您也可以在
perl
中执行类似操作:

perl -0777 -lne 's/^(repeat[ ]+\d+)\s+/\1\t/mg; s/^[ ]*>/\t\t>/mg; print' file 
//                                                                                                            
import tset flash_read, flash_writ;
vector  (      , (XMOSI, XMISO, XSCLK, XSTRMSTRT, XSTRMSCLK, XSTRMCKEN, XXTALIN, XXTALCPUEN, XHVREGON, XFDRESET, XGLDATA5, XGLDATA4, XGLDATA3, XGLDATA2, XGLDATA1, XGLDATA0):H, (XSTRMD3, XSTRMD2, XSTRMD1, XSTRMD0, XNSS3, XNSS2, XNSS1, XNSS0):H, XTECLOCK, XRXDATA, XRXENABLE, XTXDATA, XTXENABLE, XNRESET, XTCK, XTMS, XTDI, XTDO, XNTRST)
{
repeat 2    > flash_writ X0X00X0XXXXXXXXX 0000XXXX X 0 L X X 0 1 0 0 X 0; // XNTRST
repeat 9    > flash_writ X0X00X0XXXXXXXXX 0000XXXX X 0 L X X 0 1 1 0 X 1; // Test Logic Reset
            > flash_writ X0X00X0XXXXXXXXX 0000XXXX X 0 L X X 0 1 0 0 X 1; // Run Test Idle
repeat 2    > flash_writ X0X00X0XXXXXXXXX 0000XXXX X 0 L X X 0 1 1 0 X 1; // Select IR
perl -lne ' if (/^repeat[\h]+\d+/) {$ll=$_; next} 
            if (/^\h+>/) {$_=sprintf("%-21s%s",$ll,$_);$ll="";}
            print' file
或者,如果您喜欢简洁而不是清晰:

awk '/^repeat/{p=$0;next} /^ >/{$0=sprintf("%-21s",p)$0;p=""} 1' file
如果需要“就地”编辑,请使用GNU awk:

awk -i inplace '/^repeat/{p=$0;next} /^ >/{$0=sprintf("%-21s",p)$0;p=""} 1' file

老兄,谢谢你这么做。实际上你的想法奏效了。只是做了一些小的调整。我的最后一个工作表达式是perl-0777-lne的/^[]*(>)/\t\t$1/mg;s/^(重复[]+\d+\s+/$1\t/mg;print'inputfile | tee output fileI我试图在perl-0777之后添加一个-i开关,以查看是否可以将更改应用到适当的位置,但它似乎不起作用。现在,我可以将输出流重定向到一个新文件,但很想知道为什么就地不起作用。@user3791998
-I
选项接受一个可选参数用于备份。。因此,如果你尝试将该选项与其他选项结合使用,它将不起作用。。。请尝试
perl-i-0777-lne'…'
Hi Sundeep,谢谢您的提示。是的,我试着做一个perl-0777-ilne,但没有成功。在将其更改为perl-i-0777-lne之后,它运行良好。perl-0777-i-lne也起了作用。因此,只要这个开关没有与其他开关组合,命令中-i开关的位置就无关紧要。嗨,埃德,谢谢你的回答。解决方案非常好。在看了这三种解决方案之后,我更喜欢第一种解决方案,因为它清晰明了。然而,稍微解释一下awk的3行代码是怎么做的,可能会帮助我节省一些时间来解码它们,或者可能会帮助其他awk新手,他们可能会尝试识别这些代码,将这些想法应用到他/她的特定用例中。因此,我的理解如下:(1)在第一行,awk查找以repeat开头的行,如果找到这样的行,它将其存储在名为pfx的变量中,然后移动到下一行。(2) 在第二行中,如果找到以>开头的下一行,则将存储在pfx中的内容置于22个字符长度的左对齐格式字符串中,后跟当前行的内容。然后将pfx变量的值重置为“”,以便对于所有其他行,在左对齐22个空格后打印>。(3)awk程序的第三行只是说,通过满足上述两个条件来打印所有行。对,我没有对代码进行注释,因为它足够简单,任何新手只要想一想就可以理解,而且他们通过研究和思考了解到更多关于awk的信息,而不是仅仅通过这个答案。您可以随时向脚本中添加“print”,查看变量的值,如果有任何不理解的地方。