简体   繁体   English

如果在行中找到字符串,请用前一行sed的字符串替换

[英]If string is found in line, replace with string from previous line, sed

I have a few thousand lines of code spread out across multiple files that I need to update. 我有数千行代码分布在需要更新的多个文件中。 Right now they are like so: 现在他们就像这样:

active_data(COPIED),

I need to replace all instances of COPIED (only in these lines) with the text inside the parenthesis on the previous line. 我需要将COCOPED的所有实例(仅在这些行中)替换为上一行中括号内的文本。 So it total the code currently might look like: 因此,总的来说,当前的代码可能如下所示:

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

and I want it to look like: 我希望它看起来像:

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

I can find the lines to be replaced easily enough, and could replace the with some static string with no problem, but I'm not sure how to pull the data from the previous line and use that. 我可以很容易地找到要替换的行,可以用一些静态字符串替换,这没有问题,但是我不确定如何从前一行中提取数据并使用它。 I'm sure its pretty simple but can't quite figure it out. 我敢肯定它很简单,但是还不太清楚。 Thanks for the help. 谢谢您的帮助。

(I could see using AWK or something else for this too if sed won't work but I figure sed would be the best solution for a one time change). (如果sed不起作用,我也可以看到使用AWK或其他方法,但我认为sed是一次更改的最佳解决方案)。

sed could work but awk is more natural: sed可以工作,但是awk更自然:

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

    Use open or claose parens as the field separator. 使用开放式或宽松的括号作为字段分隔符。

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

    If the second field is COPIED , then replace it with prev . 如果第二个字段已COPIED ,则将其替换为prev

  • prev=$2

    Update prev . 更新prev

  • 1

    This is cryptic shorthand which means print the line. 这是个隐秘的缩写,表示打印行。 It is equivalent to {print $0;} . 等效于{print $0;}

How awk sees the fields 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=,

Changing in-place all files in a directory 就地更改目录中的所有文件

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

Or, if you have a modern GNU awk: 或者,如果您拥有现代的GNU awk:

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

This might work for you (GNU sed): 这可能对您有用(GNU sed):

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

This keeps a moving window of 2 lines open throughout the length of the file and uses pattern matching to effect the required result. 这将在整个文件的整个长度中保持2行移动窗口的打开,并使用模式匹配来实现所需的结果。

With GNU awk for FPAT: 使用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),

With other awks: 与其他awk:

$ 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),

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM