仅当模式跟随某物时才查找和替换

Find-and-replace only when the pattern is following by something

我有很多包含以下模式的 Jupyter 笔记本

try:
    import tensorflow as tf
except:
    %pip install tensorflow
    import tensorflow as tf

根据pylint,我应该提供一个更具体的异常对象,即

try:
    import tensorflow as tf
except ModuleNotFoundError:
    %pip install tensorflow
    import tensorflow as tf

这是基本的想法,但更准确地说,笔记本本质上是 JSON 文件,它们实际上包含类似

的内容
"try:\n",
"    import tensorflow\n",
"except:\n",
"    %pip install tensorflow\n",
"    import tensorflow\n",

由于有数百个笔记本,我无法手动查看它们,所以我打算用 agsed 进行查找和替换,例如

ag -l '^"except:\\n",$' | xargs sed -i '' 's/except:/except ModuleNotFoundError:/g'

但是,并非所有 except: 块都包含 %pip install 语句。仅当 except: 后跟 %pip install 时,我如何才能将所有 except: 替换为 except ModuleNotFoundError:

使用sed

$ sed '/except:/{N;/%pip install/{s/except:/except ModuleNotFoundError:/}}' input_file
try:
    import tensorflow as tf
except ModuleNotFoundError:
    %pip install tensorflow
    import tensorflow as tf
  • 匹配行 except:
  • 如果 N; 下一行包含字符串 %pip install 那么
  • 仅将 except:%pip install 匹配为下一行并将其更改为 except ModuleNotFoundError:

另一个使用 sed 的选项可能是:

sed '/except:/{N;/:\n[[:space:]]*%pip install/{s// ModuleNotFoundError&0/}}' file
  • 匹配时except:
  • 使用 N
  • 读取(附加)模式 space 的下一行
  • 如果当前模式 space 匹配 :\n[[:space:]]*%pip install
  • 使用最后匹配的模式 // 并替换为 ModuleNotFoundError 后跟完整匹配 &0

此模式 :\n[[:space:]]*%pip install 匹配 : 换行符和可选的 spaces 然后 %pip install

输出

try:
    import tensorflow as tf
except ModuleNotFoundError:
    %pip install0 tensorflow
    import tensorflow as tf