-1

In my codebase i've lines like

@driver.find_element(:link, "Create").click

and sometimes there can be any string inside '(' and ')'

eg: @driver.find_element(:name, from_email).click

I want to replace the lines

@driver.find_element(:link, "Create").click

and

@driver.find_element(:name, from_email).click

as

click(:link, "Create")

and

click(:name, from_email)

I want the parenthesis and the words inside the parenthesis to be retained after replacing @driver.find_element with click.

Is there a way to do this across files in different folder levels?

0

replace a part of the string across all files in a directory

find + sed solution:

find yourfolder -type f -print0 \
    | xargs -0 sed -i.bak -E 's/@driver\.find_element\(([^()]+)\)\.click/click(\1)/'
0

Using sed:

sed 's/@driver.find_element\((:name, from_email)\).click/click\1/;s/@driver.find_element\((:link, "Create")\).click/click\1/'

Examples:
File before:

cat clickReplace 
@driver.find_element(:link, "Create").click
@driver.find_element(:name, from_email).click
@driver.find_element(:name, foobar).click
@driver.find_element(:link, foobar).click

File after:

sed 's/@driver.find_element\((:name, from_email)\).click/click\1/;s/@driver.find_element\((:link, "Create")\).click/click\1/' clickReplace 
click(:link, "Create")
click(:name, from_email)
@driver.find_element(:name, foobar).click
@driver.find_element(:link, foobar).click

Use sed -i to change the files "in place".

To do it recursively, use find to wherever in your filesystem the files are. E.g.:

find /path/to/files/ -type f -exec \
sed -i 's/@driver.find_element\((:name, from_email)\).click/click\1/;s/@driver.find_element\((:link, "Create")\).click/click\1/' {} +
0

Using sed with extended regex support (-r or -E):

$ sed -E 's/.*(\(.*\))[.](.*)/\2\1/g' <<<$'@driver.find_element(:link, "Create").click'
click(:link, "Create")

$ sed -E 's/.*(\(.*\))[.](.*)/\2\1/g' <<<$'@driver.find_element(:name, from_email).click'
click(:name, from_email)

Classic sed , basic regex:

$ sed 's/.*\((.*)\)[.]\(.*\)/\2\1/g' <<<$'@driver.find_element(:link, "Create").click'
click(:link, "Create")

With awk:

$ awk -F'[.(]' '{print $NF "(" $(NF-1)}' <<<$'@driver.find_element(:name, from_email).click'    
click(:name, from_email)
0

Given a single file, the following sed command will do the substitution on that file:

sed 's/@driver.find_element(\(.*\)).click/click(\1)/' file >file.tmp && 
mv file.tmp file

We'd like to find all files in a file hierarchy and execute that on all of them:

find . -type f \
    -exec sh -c \
    'for n; do
        sed "s/@driver.find_element(\(.*\)).click/click(\1)/" "$n" >"$n.tmp" &&
        mv "$n.tmp" "$n"
    done' sh {} +

If you only want to modify files with a particular name, for example *.js, just add -name '*.js' before the -exec.

This assumes that adding .tmp to the end of a filename won't accidentally overwrite an existing file.


I purposefully did not use sed -i since the -i is notoriously non-portable between sed implementations.

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.