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

Posted

技术标签:

【中文标题】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 【发布时间】:2021-11-15 01:38:57 【问题描述】:

我有以下代码块:

# 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/(.*)(.*\nMATCH\1REPLACE(.*))$/\3\2/;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/(.*)(.*\nMATCH\1REPLACE(.*))$/\3\2/;ta;s/MATCH\n.*//''

我该如何解决这个错误?

【问题讨论】:

必须sed吗?使用其他东西,例如,使用pythonhow to manage to replace big blocks 基本上是一样的,只是你要读多行,然后用正则表达式匹配多行。 sed 很难,sed -z 更简单。 | of Python files by this new block : 顺便说一句,用它做一个 python 函数/库来缓解未来的变化不是更好吗? 编者注:如果text is provided as images,并且没有按请求修复,可以关闭删除。 【参考方案1】:

这可能对你有用(GNU sed):

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

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

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

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

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

替代方案:

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

或者:

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

【讨论】:

非常感谢!你能看看我上面的 UPDATE 我提到我得到的错误。问候 @youpilat13 似乎第二次 sed 调用开始了 ``

以上是关于sed:如果检查文件中存在代码块,则在大量文件上用另一个代码块替换一大块代码的主要内容,如果未能解决你的问题,请参考以下文章

如果创建文件不存在,如何创建目录?

检查列是不是已存在,如果不存在,则在 sqlite 中更改表

如何查找多个文件、检查重复文件并用 bash、sed 脚本替换

如果目标文件不存在,则在 Node.js 中异步重命名文件

如果一行不存在,则在 Python 中相应地检查并赋予一个值

Erlang:如果列表中存在字符,则在插入文本时检查字符