jsonsedreplaceag

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


I have a lot of Jupyter notebooks that contain the following pattern

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

According to pylint, I should provide a more specific exception object, i.e.

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

That's the basic idea, but to be more precise, the notebooks are essentially JSON files, and they actually contain something like

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

Since there are hundreds of notebooks, I cannot go over them manually, so I planned to do a find-and-replace with ag and sed, e.g.

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

However, not all except: blocks contain %pip install statements. How can I replace all except: with except ModuleNotFoundError: only if it's followed by a %pip install?


Solution

  • Using 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