I have a Java project that has many lines that look like this:
myMethod("some text here ..."
+ " ... more text here"
+ " ... and even more text here");
I need to perform a bash search for this:
"some text here ... ... more text here ... and even more text here";
I have tried things like this:
# Filtering for text between the two parenthesis
$ grep -rn "myMethod" . | awk -F\( '{print $2}' | awk -F\) '{print $1}' | sort | uniq
# replacing the `"$\n` with nothing
$ grep -rn "myMethod" . | sed -e 's/"$\n\s//g' | sort | uniq
# same
$ grep -rn "myMethod" . | sed -e ':a;N;$!ba;s/"$\n/,/g' | sort | uniq
However, none of these is giving me what I want, which is all of the unique Strings being passed into the myMethod method.
So, how can I go about replacing or filtering out "$\\n
(quote end-of-line newline) using grep, awk, and sed in bash?
Try this ( GNU grep
and GNU sed
, I believe you are using them):
$ cat file
myMethod("some text here ..."
+ " ... more text here"
+ " ... and even more text here");
$ grep -rzn "myMethod" . | sed -rn '/myMethod/{:a;s/\)//;tb;N;ba;:b;s/\n//g;s/[^"]*$//;:c;s/^[^"]*"([^"]*)"(.*)/\2\1/;tc;p;}'
some text here ... ... more text here ... and even more text here
$ grep -rzn "myMethod" . | sed -rn '/myMethod/{:a;s/\)//;tb;N;ba;:b;s/\n//g;s/[^"]*$//;:c;s/^[^"]*"([^"]*)"(.*)/\2\1/;tc;s/^/"/;s/$/";/;p}'
"some text here ... ... more text here ... and even more text here";
I believe it will work on multiple files and multiple occurrences.
I used sed
to read after lines until it finds close paren )
and then concatenate.
Is this what you're trying to do (using GNU sed for -z
and recognition of \\n
)?
$ sed -z 's/"\n+ "//g' file
myMethod("some text here ... ... more text here ... and even more text here");
$ sed -z 's/"\n+ "//g' file | sed -n 's/^myMethod("\([^"]*\).*/\1/p'
some text here ... ... more text here ... and even more text here
If the string being passed to myMethod can contain escaped "
s then you'd just need to tell us how they're escaped (doubled? backslashed? something else?) and then they'd be easy to handle.
try if this works for you:
awk -F'"' '/^myMethod\(/,/\);$/{str = str " " $2}END{print str}' file
For your input, this will yield " some text here ... ... more text here ... and even more text here". you can fix the leading space easily if needed.
Basically use the range pattern: search only between string myMethod(
and the end of function call );
and then grab and concatenate $2
. This will not work if multiple function arguments on the same line though. you might also need to consider the white spaces before myMethod(
and after );
.
something that works exactly on your provided strings and formatting (quotes and "+" symbols included) would look like this:
>cat my_file.txt
myMethod("some text here ..."
+ " ... more text here ..."
+ " ... and even more text here");
other lines
and some other");
>sed -n '/myMethod/,/");/p' my_file.txt | sed -e ':a;N;$!ba;s/\n/ /g' -e "s/\"//g" -e "s/\+//g" -e "s/myMethod//g"
(some text here ... ... more text here ... ... and even more text here);
first sed extracts everything between string [myMethod] and first occurrence of string [");]
then we have another sed and first expression eliminates all newlines character, second expression eliminates the double quotes, 3rd expression eliminates the "+" symbols and finally the last expression removes the "myMethod" string from final output
if you want this absurdly done, you can add [-e "s/[()]/\\"/g"] to transform the leading and ending parentheses () of output, into double quotes "
LE: this will obviously mess up with your code if you have any of the following characters inside you code: [+"()myMethod]
No need for other tools; this can be done with bash alone.
$ s=$'myMethod("some text here ..."\n+ " ... more text here"\n+ " ... and even more text here");'
$ echo "$s"
myMethod("some text here ..."
+ " ... more text here"
+ " ... and even more text here");
$ t="${s//$'\n'/ }"
$ t="${t//\" + \"/ }"
$ t="${t#myMethod(\"}"
$ t="${t%\");}"
$ echo "$t"
some text here ... ... more text here ... and even more text here
This uses a bash feature called "pattern substitution" which is part of "Parameter Expansion" which you can read about on bash's man page or the official bash documentation .
This will go (locally in current dir) through all the files that have string myMethod
in them, reading the method until enclosing signal );
and replacing it with a one liner:
>>cat my_file.txt
random first line
random second line
myMethod(first line of code
second line of code
third line of code);
# notice above method ending in string ");". This is important to mark the enclosing of the method.
# this string should not be present anywhere else withing the content of the method
other lines
and some other");
>>cat other_file.txt
myMethod("text in other file ..."
+ " ... yet more text from other file ..."
+ " ... and even more text here from the second file"); # ending of method
other lines
and some other");
ACTUAL COMAND
>>for file_containing_myMethod in `grep -l "myMethod" *`; do ONE_LINER=`sed -n '/myMethod/,/);/p' ${file_containing_myMethod} | sed -e ':a;N;$!ba;s/\n/ /g'`; sed -i "/myMethod/,/);/{/);/ s/.*/${ONE_LINER}/; t; d}" ${file_containing_myMethod}; done
random first line
random second line
myMethod(first line of code second line of code third line of code);
# notice above method ending in string ");". This is important to mark the enclosing of the method.
# this string should not be present anywhere else within the content of the method
other lines
and some other");
myMethod("text in other file ..." + " ... yet more text from other file ..." + " ... and even more text here from the second file"); # ending of method
other lines
and some other");
Please note that when you test you should eliminate the -i
flag from the last sed
. -i
will change/rewrite your files instantly, and you don't want that before testing.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.