如果在行中找到string,则用上一行中的字符串替换sed

时间:2015-08-05 22:31:33

标签: regex linux sed

我有几千行代码分布在我需要更新的多个文件中。现在他们是这样的:

active_data(COPIED),

我需要用前一行括号内的文本替换COPIED的所有实例(仅在这些行中)。因此,目前代码的总代码如下:

current_data(FOO|BAR|TEXT),
active_data(COPIED),

我希望它看起来像:

current_data(FOO|BAR|TEXT),
active_data(FOO|BAR|TEXT),

我可以很容易地找到要替换的行,并且可以用一些静态字符串替换没有问题但是我不确定如何从前一行中提取数据并使用它。我敢肯定它非常简单,但无法弄明白。谢谢你的帮助。

(如果sed不起作用,我可以看到使用AWK或其他东西,但我认为sed将是一次性更改的最佳解决方案。)

3 个答案:

答案 0 :(得分:2)

sed可行,但awk更自然:

$ awk -F'[()]' '$2 == "COPIED" {sub(/COPIED/, prev)} {prev=$2;} 1' file
current_data(FOO|BAR|TEXT),
active_data(FOO|BAR|TEXT),
  • -F'[()]'

    使用开放或密合的parens作为字段分隔符。

  • $2 == "COPIED" {sub("COPIED", prev)}

    如果第二个字段为COPIED,则将其替换为prev

  • prev=$2

    更新prev

  • 1

    这是神秘的简写,意味着打印线。它相当于{print $0;}

awk如何看到字段

$ awk -F'[()]' '{for (i=1;i<=NF;i++)printf "Line %s Field %s=%s\n",NR,i,$i;}' file
Line 1 Field 1=current_data
Line 1 Field 2=FOO|BAR|TEXT
Line 1 Field 3=,
Line 2 Field 1=active_data
Line 2 Field 2=COPIED
Line 2 Field 3=,

更改目录中的所有文件

for file in *
do
  awk -F'[()]' '$2 == "COPIED" {sub("COPIED", prev)} {prev=$2;} 1' "$file" >tmp$$ && mv tmp$$ "$file"
done

或者,如果你有一个现代的GNU awk:

awk -i inplace -F'[()]' '$2 == "COPIED" {sub("COPIED", prev)} {prev=$2;} 1' *

答案 1 :(得分:1)

这可能适合你(GNU sed):

sed 'N;s/\((\([^)]*\)).*\n.*(\)COPIED/\1\2/;P;D' file

这样可以在文件的整个长度上保持2行的移动窗口,并使用模式匹配来实现所需的结果。

答案 2 :(得分:1)

使用GNU awk for FPAT:

$ awk -v FPAT='[(][^)]*[)]|[^)(]*' -v OFS= '$2=="(COPIED)"{$2=prev} {prev=$2; print}' file
current_data(FOO|BAR|TEXT),
active_data(FOO|BAR|TEXT),

其他问题:

$ awk '
match($0,/\([^)]*\)/) {
    curr = substr($0,RSTART,RLENGTH)
    if (curr == "(COPIED)") {
        $0 = substr($0,1,RSTART-1) prev substr($0,RSTART+RLENGTH)
    }
    else {
        prev = curr
    }
}
{ print }
' file
current_data(FOO|BAR|TEXT),
active_data(FOO|BAR|TEXT),