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 ther
flag to return the result as the replacement stringe
flag allows to use expression instead of string- use
perl -i -0777 -pe
for inplace editing