Regex sed:保持模式并重新排列行

Regex sed:保持模式并重新排列行,regex,variables,sed,awk,Regex,Variables,Sed,Awk,我不确定我是否可以完全使用sed来实现这一点: 我正试图像这样重新排列线条 GF:001,GF:00012,GF:01223<TAB>XXR GF:001,GF:00012,GF:01223,GF:0666<TAB>XXXR3 但是,如果有人知道一种仅使用sed解决此问题的方法,请在此处发布…如果您不严格要求sed,awk擅长这样做: awk -F'\t|,' '{ i=1; do { printf("%s\t%s\n",$i,$NF); i++;} while (

我不确定我是否可以完全使用sed来实现这一点:

我正试图像这样重新排列线条

GF:001,GF:00012,GF:01223<TAB>XXR
GF:001,GF:00012,GF:01223,GF:0666<TAB>XXXR3

但是,如果有人知道一种仅使用
sed解决此问题的方法,请在此处发布…

如果您不严格要求sed,awk擅长这样做:

awk -F'\t|,' '{ i=1; do { printf("%s\t%s\n",$i,$NF); i++;}  while ( i<NF ); }' inputfile

awk-F'\t |,''{i=1;do{printf(“%s\t%s\n”,$i,$NF);i++}而(i它可以在
sed
中完成,尽管我可能会使用Perl(或awk或Python)来完成

我声称这个解决方案并不优雅,但暴力和无知有时是值得的。我创建了一个名为
sed.script的文件,它包含:

/\(GF:[0-9]*\),\(.*\)<TAB>\(.*\)/{
:redo
s/\(GF:[0-9]*\),\(.*\)<TAB>\(.*\)/\1<TAB>\3@@@@@\2<TAB>\3/
h
s/@@@@@.*//
p
x
s/.*@@@@@//
t redo
d
}
其中,
input
包含问题中显示的两行。它生成输出:

GF:001<TAB>XXR
GF:00012<TAB>XXR
GF:01223<TAB>XXR
GF:001<TAB>XXXR3
GF:00012<TAB>XXXR3
GF:01223<TAB>XXXR3
GF:0666<TAB>XXXR3
GF:001XXR
GF:00012XXR
GF:01223XXR
GF:001XXXR3
GF:00012xxr3
GF:01223XXXR3
GF:0666XXXR3
(我故意将
误解为5个字符的序列而不是单个制表符;您可以很容易地修复答案以处理实际的制表符。)

sed
脚本说明:

  • 查找出现多个
    GF:nnn
    并用逗号分隔的行(我们不需要处理包含一个此类事件的行)。仅在这些行上执行脚本的其余部分。其他任何内容都将以不变的方式传递(打印)
  • 创建一个标签,以便我们可以返回到它
  • 将该行拆分为3个记住的部分。第一部分是初始GF信息;第二部分是任何其他GF信息;第三部分是
    之后的字段。将其替换为第一个字段、
    、第三个字段、不可信的标记模式(
    @@
    )、第二个字段、
    、第三个字段
  • 将修改后的行复制到保留空间
  • 将标记图案删除到底
  • 印刷品
  • 将保持空间交换到图案空间
  • 移除所有标记图案之前的内容(包括标记图案)
  • 如果我们完成了任何工作,请返回
    redo
    标签
  • 删除剩下的内容(已打印)
  • 脚本块的结尾

这是一个简单的循环,可以在每次迭代中将模式的数量减少一个。

您可以直接使用awk进行此操作:

$ awk '{gsub(/,/, "\t" $NF "\n");print}' input 
在本例中,我们只需将逗号替换为与最后一个字段连接的制表符(
NF
存储记录的字段数;
$NF
获取与换行符连接的
NF
第个字段)。然后,打印结果

它也可以用sed解决,以类似的方式解决,但IMHO比Jonathan解决方案要好一点(我应该说,Jonathan解决方案非常复杂)

然后我们将图案空间的内容复制到保留空间:

h
x
现在,我们用一个制表符替换从第一个逗号到制表符的所有内容:

 s/,.*<TAB>/<TAB>/
…并检索保留空间的内容:

h
x
由于我们打印了第一行,其中包含第一个
GF:XXX
图案,然后是最后一个
XXR
图案,因此我们从行中删除了第一个
GF:XXX
图案:

 s/^[^,]*,//
如果执行了替换,我们将转到脚本的开头:

t BEGIN

所有内容都再次应用于同一行,只是现在这一行不再有第一个
GF:XXX
模式。OTOH,如果没有进行替换,那么当前行的处理就完成了,我们不再跳转到开始处。

我花了3个小时才完成


sed-re:a;s/(GF[0-9]*[^,]*),([^
awk-F'[,\t]'''{for(i=1;我感谢你!我是通过perl完成的……不过我应该看看
awk
。真的令人印象深刻!我认为sed的功能不足以做循环,但是如果你有一个GOTO构造函数,你可以模拟循环。感谢Jonathan的证明!啊,是的,备受追捧的GOTO构造-软件工程师的梦想:-).awk解决方案是快速的
real 0m6.496s用户0m1.555s sys 0m0.109s
sed解决方案对于28k行文件来说速度较慢
real 0m27.177s用户0m23.080s sys 0m0.129s
,这很有意义,实际上,因为sed应该迭代行中模式的每个实例。我发布了一个sed解决方案,因为它在sp中具体化,但这可能不是该案例的最佳解决方案。无论如何,我认为awk解决方案更好,事实上,但我发现这个问题是一个很棒的sed练习:)@埃德蒙顿:那是因为你落后了30年,而我只有3天。这不是因为awk有清晰、简单的语法,而sed对于任何比一行简单替换更复杂的东西都需要罗塞塔石、3个智者和一个蝙蝠侠解码环。@埃德蒙顿,我真的需要做出决定。根据你的建议,我能完成9个吗0%的任务单独使用awk。我真的想只使用其中一个,这样我就可以详细讨论,但无法决定是哪一个。如果你说90%的任务可以使用awk完成,那么我会使用它。你可以单独使用awk完成100%的文本处理任务。不过,grep、sed等可以稍微更快/更容易地用于小任务。大多数您可以在awk中执行复杂的操作您也可以在sed中执行复杂的操作,但生成的awk将清晰、简单、快速且易于维护,而等效的sed将花费大量的时间来编写,并且即使是最小的需求更改也需要完全重写。了解awk-您应该使用sed的内容非常简单您无需花费任何精力来学习它,您只需从几个示例中学习。为了您的利益,我刚刚添加了对我的awk脚本的解释。请注意,我所做的只是解释了几个最基本的awk概念,我希望您能够从中理解脚本。将其与复杂性和特殊性进行比较本页对sed脚本的解释是不完整的,请认真想象自己试图构建或调试awk和sed脚本
p
x
 s/^[^,]*,//
t BEGIN
awk -F'[,\t]' '{for (i=1;i<NF;i++) print $i"\t"$NF}' file