1

In all my python scripts, I'd like to replace the 2 consecutive lines

import matplotlib as mpl
mpl.style.use(mpl_plt_default_template)

with just the line

plt.style.use(mpl_plt_default_template)

So far, I've found a way to replace 2 consecutive lines with an expression applied to each of these lines, but not how to replace the 2 lines with a single line altogether. Regarding my unsuccessful approach it applied the following sed-string:

sed '/import matplotlib as mpl$/N;//s/mpl.style.use(mpl_plt_default_template)/plt.style.use(mpl_plt_default_template)/g'

Note that the first line (import matplotlib as mpl) can also occur at other places in the file and should be left unchanged there, so the goal is to perform a replacement only if both lines are found one following the other in the order given.

EDIT on additional scope involving find:

The ultimate goal is to replace these 2 lines in several textfiles found via the find - command using a pipeline similar to the following manner:

find /path/to/dir/ -type f -exec sed 'old-lines/s/single-new-line' {} \;

System-specifics:

OS: Lubuntu 20.04 LTS

0
5

To edit a file, use a scriptable text editor, such as Ed or Ex (both POSIX editors). The syntax is very similar.

printf '%s\n' '/^import matplotlib as mpl$/d' 's/mpl/plt' 'w' 'q' | ed -s file
printf '%s\n' '/^import matplotlib as mpl$/d' 's/mpl/plt' 'x' | ex file
  • printf '%s\n' supplies commands to the editor.

  • /^import matplotlib as mpl$/d deletes the first line matching the pattern.

  • s/mpl/plt performs the substitution on the next line.

  • w and q or x save the changes.

If you really want Sed,

sed '/^import matplotlib as mpl$/N; s/.*\nmpl/plt/' file

Addressing your expanded question:

find /path/to/dir/ -type f -exec sh -c '
    printf "%s\n" "/^import matplotlib as mpl\$/d" "s/mpl/plt" "w" "q" |
    ed -s "$1"' sh {} \;
12
  • How can I implement this in a pipeline starting with find, such as e.g.: find /path/to/dir/ -type f -exec printf '%s\n' '/^import matplotlib as mpl$/d' 's/mpl/plt' 'x' | ex file {} \; – Andreas L. Jan 4 at 13:17
  • 2
    @AndreasL. If you have another question, please consider opening another question. – Kusalananda Jan 4 at 13:27
  • @Kusalananda, I edited my initial question so that everything is included. I hope this can be answered here as well, that everything stays in the same thread. Basically, Quasimodo just needs to extend his answer. – Andreas L. Jan 4 at 15:44
  • 1
    @AndreasL. find ... -exec sh -c 'printf "..." "..." ... | ed -s "$1"' sh {} \; – Kusalananda Jan 4 at 16:33
  • 1
    @AndreasL. Have a look at the last part of the answer that I added. Pay attention to the types of quotes use and how $ is escaped in the sed expression. – Kusalananda Jan 4 at 17:54
3

If it doesn't have to be sed, you can use awk for the task:

awk '$0=="import matplotlib as mpl" {buf=$0; next}
     buf {if (/^mpl\.style\.use/) {sub(/^mpl/,"plt")} else {print buf}; buf=""} 1' inputfile
  • When a line exactly reading import matplotlib as mpl is encountered, it will store it in a buffer buf and skip execution to the next line.
  • If the buffer variable is set, and the current line starts with mpl.style.use, it will replace that part of the current line with plt.style.use and discard the buffer content.
  • If the buffer variable is set, but the current line does not match the "second line" pattern, it will print the buffer content before printing the current line. The buffer is then cleared afterwards.
  • For all lines encountered while the buffer is empty, we simply print the line as is.

If you require a more exact match of the second line, change the second rule to

buf {if ($0=="mpl.style.use(mpl_plt_default_template)" {sub(/^mpl/,"plt")} else {print buf}; buf=""}
1
  • Thanks for the alternative. However, when I tried the following command, it showed an endless output stream (probably going through all files) which wasn't even finished after 20 minutes, so I stopped it: find /home/andylu/Desktop/Python/Scripts/ -not -path "*.history*" -not -path '*__pycache__*' -type f -exec awk '$0=="import matplotlib as mpl" {buf=$0; next} buf {if (/^mpl\.style\.use/) {sub(/^mpl/,"plt")} else {print buf}; buf=""} 1' {} \; – Andreas L. Jan 4 at 17:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.