用sed条件替换字符串片段(单行!)

时间:2014-07-03 07:55:15

标签: bash sed tcsh

我正在尝试使用 sed 处理 diff 操作的结果。这是我的 diff 输出,我输入 sed

3d2
< 12-03-22_JET_D_CL_UR_l4053_0061 True_Warning All 9 149261 
62a62
> 13-01-29_VUE_EPM3_v37_CSAV2_0370 True_Warning All 13 22125 
68c68
< 13-05-14_Regular_Front_0062 True_Warning All 13 123383 
---
> 13-05-14_Regular_Front_0062 True_Warning All 21 123383 
119c119
< CADS4_PMP363_20130202_DPH_069 True_Warning All 13 233405 
---
> CADS4_PMP363_20130202_DPH_069 True_Warning All 9 233409 
149c149
< CADS4_PMP363_20130315_Fujifilm_UK_186 True_Warning All 21 18611 
---
> CADS4_PMP363_20130315_Fujifilm_UK_186 True_Warning All 17 18615 

我需要整理差异字符串并在字符串中添加第3个字,并使用&#34; Old&#34;或&#34;新&#34; - 取决于第一个字符。到目前为止我的最大努力是

diff new_jumps/true.jump old_jumps/true.jump | sed -n "/^[<>]/ s:\(.\) \(\S\+\) \(.\+\):\2 \1,\3: p" | replace ">" Old | replace "<" New

这给了我这个结果(正是我想要的)。

12-03-22_JET_D_CL_UR_l4053_0061 New,True_Warning All 9 149261 
13-01-29_VUE_EPM3_v37_CSAV2_0370 Old,True_Warning All 13 22125 
13-05-14_Regular_Front_0062 New,True_Warning All 13 123383 
13-05-14_Regular_Front_0062 Old,True_Warning All 21 123383 
CADS4_PMP363_20130202_DPH_069 New,True_Warning All 13 233405 
CADS4_PMP363_20130202_DPH_069 Old,True_Warning All 9 233409 
CADS4_PMP363_20130315_Fujifilm_UK_186 New,True_Warning All 21 18611 
CADS4_PMP363_20130315_Fujifilm_UK_186 Old,True_Warning All 17 18615 

我的问题是 - 我怎样才能在 sed 单行内更改条件表达式,以免之后无需使用替换? (我认为这是可能的) 提前致谢

修改

我知道,我错过了链接 sed 表达式的选项,但我想到的是 - 是否可以在一次替代操作中

3 个答案:

答案 0 :(得分:2)

通过使用分号(;)向sed添加更多命令,如下所示:

diff new_jumps/true.jump old_jumps/true.jump | sed -n "/^[<>]/ s:\(.\) \(\S\+\) \(.\+\):\2 \1,\3:; s/</New/gp; s/>/Old/gp"

答案 1 :(得分:1)

使用awk我得到更快的响应。试试这个:

diff new_jumps/true.jump old_jumps/true.jump | awk '{ if($1=="<" || $1==">"){($1=="<")?temp="New,":temp="Old,";print $2,temp$3,$4,$5}}'

这是Jidder提出的另一个解决方案:

awk '/^</{i="old,"}/^>/{i="new,"}i{$2=$2" "i;print;i=0}'

答案 2 :(得分:0)

@volcano:这是sed中的单行解决方案,但依赖于与shell的交互。恕我直言,如果你想只有一个sed替换命令,你无法避免这种行为:你必须向shell输出在线上看到第一个字符的信息,shell有点映射到“Old”或“新的“字符串,并将结果返回给sed。

因此我们必须在shell中定义东西......;)

replace() { if [ "$1" == ">" ] ; then echo -n "Old"; else echo -n "New" ; fi }
export -f replace
sed -n '/^[<>]/ s:\(.\) \(\S\+\) \(.\+\):echo "\2 $(replace \\\1),\3";:ep' yourfile

请注意,替换命令的e标志是GNU sed扩展,我们在此处使用它来避免显式调用shell。如果你不使用GNU sed,你可以简单地用以下代码替换上面的最后一行:

sed -n '/^[<>]/ s:\(.\) \(\S\+\) \(.\+\):echo "\2 $(replace \\\1),\3";:p' yourfile | bash

我在这里给出的解决方案受到that other one的启发。

请注意,如果你接受用他们的首字母替换你的三个字母标记“Old”和“New”,所有这些体操都是可以避免的,因为那样我们就可以整齐地使用y命令来一个tr时尚,同样:

sed -n '/^[<>]/ y/<>/ON/; s:\(.\) \(\S\+\) \(.\+\):\2 \1,\3:p' yourfile