sed:如果检查文件中存在代码块,则在大量文件上用另一个代码块替换一大块代码

sed: replace a big block of code by another on a large number of files if the code block exists in the inspected files

我有以下代码块:

# Block bias spectro + pshot and correlations
FISH_super_flat_GCsp[0:7,0:7] = FISH_EUCLID_GCsp_flat[0:7,0:7]
FISH_super_flat_GCsp[7:17,7:17] = FISH_EUCLID_GCsp_flat[7:17,7:17]
FISH_super_flat_GCsp[0:7,7:17] = FISH_EUCLID_GCsp_flat[0:7,7:17]
FISH_super_flat_GCsp[7:17,0:7] = FISH_EUCLID_GCsp_flat[7:17,0:7]
# Block bias photo and correlations
FISH_super_flat_XC[0:7,0:7] = FISH_EUCLID_XC_flat[0:7,0:7]
FISH_super_flat_XC[20:31,20:31] = FISH_EUCLID_XC_flat[10:21,10:21]
FISH_super_flat_XC[0:7,20:31] = FISH_EUCLID_XC_flat[0:7,10:21]
FISH_super_flat_XC[20:31,0:7] = FISH_EUCLID_XC_flat[10:21,0:7]
# Block I.A and correlations
FISH_super_flat_XC[17:20,17:20] = FISH_EUCLID_XC_flat[7:10,7:10]
FISH_super_flat_XC[0:7,17:20] = FISH_EUCLID_XC_flat[0:7,7:10]

我想用这个新块替换它,如果它存在于文件中,在大量 Python 文件中:

# Block bias spectro + pshot and correlations
FISH_super_flat_GCsp[0:7,0:7] = FISH_EUCLID_GCsp_flat[0:7,0:7]
FISH_super_flat_GCsp[7:17,7:17] = FISH_EUCLID_GCsp_flat[7:17,7:17]
FISH_super_flat_GCsp[0:7,7:17] = FISH_EUCLID_GCsp_flat[0:7,7:17]
FISH_super_flat_GCsp[7:17,0:7] = FISH_EUCLID_GCsp_flat[7:17,0:7]
# Block bias photo and correlations
FISH_super_flat_XC[0:7,0:7] = FISH_EUCLID_XC_flat[0:7,0:7]
FISH_super_flat_XC[17:31,17:31] = FISH_EUCLID_XC_flat[7:21,7:21]
FISH_super_flat_XC[0:7,17:31] = FISH_EUCLID_XC_flat[0:7,7:21]
FISH_super_flat_XC[17:31,0:7] = FISH_EUCLID_XC_flat[7:21,0:7]

我知道可以使用 sed(或者肯定是 gsed,因为我在 zsh MacOS 11.3)但是我需要帮助,因为我只有一次机会(那是为什么我要备份包含所有要检查的 Python 文件的 director。

我可能会使用这样的命令:

find directory_to_replace/ -type f -name '*.py' -exec sed **UNKNOWN COMMAND** {} \;

我知道用 sed 替换单词或正则表达式(如 sed -i 's/\(pattern1\)/pattern2/g ),但我不知道如何设法替换上面的大块代码。

也许我需要将这两个块放入文本文件中并用 sed 替换处理,但这是我第一次需要进行这种操作。

更新

鉴于 @potong 完成的解决方案,我已将此命令放入脚本中并将该命令包含在所有 Python 文件的循环中:

#!/bin/bash

for i in $(find . -type f -name '*.py'); do
echo $i
gsed -e '$p;e echo MATCH;cat matchFile;echo REPLACE;cat replaceFile' -e '$d' $i |\
gsed -Ez '':a;s/(.*)(.*\nMATCHREPLACE(.*))$//;ta;s/MATCH\n.*//'
done

如您所见,我使用了 GNU sed "gsed" 因为我在 MacOS 11.6 :

不幸的是,我收到以下错误:

./script_replacement_block_synthesis.sh: line 6: syntax error near unexpected token `.*'
./script_replacement_block_synthesis.sh: line 6: `gsed -Ez '':a;s/(.*)(.*\nMATCHREPLACE(.*))$//;ta;s/MATCH\n.*//''

我该如何解决这个错误?

这可能适合您 (GNU sed):

sed -e '$p;e echo MATCH;cat matchFile;echo REPLACE;cat replaceFile' -e '$d' file |
sed -Ez ':a;s/(.*)(.*\nMATCHREPLACE(.*))$//;ta;s/(.*)MATCH\n.*//'

将匹配内容放在 matchFile 中,将替换内容放在 replaceFile 中。

将匹配项和替换项附加到相关文件并将结果通过管道传递给另一个 sed 调用。

使用模式匹配,将 matchFile 与文件中的匹配项进行匹配,并用 replaceFile 替换它并重复直到失败。

最后从原始文件的末尾删除匹配和替换文件。

选择:

cat file <(echo MATCH) matchFile <(echo REPLACE) replaceFile |
sed -zE ':a;s/(.*)(.*MATCHREPLACE(.*))$//;ta;s/(.*)MATCH.*//'

或者:

cat file <(echo MATCH) matchFile <(echo REPLACE) replaceFile |
sed -E 'H;1h;$!d;x;:a;s/(.*)(.*MATCHREPLACE(.*))$//;ta;s/(.*)MATCH.*//'