Replace anything between parentheses even if spanning multiple lines

Taking the bash answer of @Serg and converting it to use bash builtins, rather than 2 or 3 processes per line. Processes are cheap but not free!

#!/bin/bash
# Use shell builtins, read, true, false, printf
flag=false
while IFS= read -r line
do
    case "$line" in
    (*"("*) flag=true ;;
    esac

    if $flag
    then
        line=${line//line/newline} 
    fi

    printf "%s\n" "$line"

    case "$line" in
    (*")"*) flag=false ;;
    esac

done < "$1"

AWK

AWK allows executing code-block {} on range of conditions. In this case, we want to execute gsub() on every line in range from the one that contains ( to the one that contains ).

$ awk '$0~/[(]/,$0~/[)]/{gsub(/line/,"newline")};1' input.txt                                                     
another line
something else

myFunction (newline0

newline1

whatever

newline2

newline3

newline4)

some other line

Python (original answer)

Here's a quick python script that does the job:

#!/usr/bin/env python3
from __future__ import print_function
import sys

with open(sys.argv[1]) as fp:
    flag = None
    for line in fp:
        clean_line = line.strip()
        if "(" in clean_line: flag = True
        if flag:
           clean_line = clean_line.replace("line","newline")
        print(clean_line) 
        if ")" in clean_line: flag = False

Test run:

$ cat input.txt                                                                                                          
another line
something else

myFunction (line0

line1

lilne2

line3

line4)

some other line
$ ./edit_function_args.py input.txt                                                                                      
another line
something else

myFunction (newline0

newline1

newline2

newline3

line4)

some other line

BASH version

The same script, except rewritten in bash with sed

#!/bin/bash
flag=false
while IFS= read -r line
do

    if grep -q '('  <<< "$line"
    then
        flag=true 
    fi


    if $flag
    then
        line=$(sed 's/line/newline/'   <<< "$line") 
    fi

    printf "%s\n" "$line"


    if grep -q ')'  <<< "$line"
    then
        flag=false     
    fi

done < "$1"

If perl solution is okay and file is small enough to be processed as a whole:

$ perl -0777 -pe 's/\([^)]+\)/$&=~s|line|newline|gr/ge' ip.txt    
myFunction (newline0

newline1

newline2

newline3

newline4) 
  • -0777 slurp entire input file
  • \([^)]+\) pattern to match - ( followed by non ) characters and ending with )
  • $&=~s|line|newline|gr the matched pattern is referenced here using $& and the desired replacement (line to newline) is done. Note the r flag to return the result as the replacement string
  • e flag allows to use expression instead of string
  • use perl -i -0777 -pe for inplace editing