2

I want to search my code base for ocurrences of a string, and then get the formatted output as filename, line number, and code lide. I got it as I wanted on the first line of the output, but the coming lines loses the wanted formatting.

$ find src/ -name "*.js" | xargs grep --null -E -n 'filter\(|map\(' | xargs -0 printf "%-100s%-5s%-100s" > test.txt

The output is as follows: (scroll right to see the complete line)

src/components/AppRouterSwitch.js                                                                   15:    return _Routes.map((route, index) => {
src/components/forms/UserEditForm/UserEditForm.js36:    const options = UserTypes.map((type, index) => <option key={index} value={type.type}>{type.name}</option>);
src/components/pages/AdminPage/SolutionManagementEditPage/SolutionManagementEditPage.js119:        templates:state.templates.filter(item=>item.SOLUTIONID ==id)
src/components/pages/AdminPage/SolutionManagementEditPage/SolutionManagementEditPage.js120:            .map(item=>{return{

The first row looks just as I want it. The following loses the desired formatting. Ending the printf format string with /n doesn't do the trick.

3
  • 1
    Try to use the standard option of grep -l (a lowercase L)
    – malyy
    Commented Nov 13, 2018 at 9:59
  • 1
    @malyy I tried that with some variations but no success. I don't see how the -l option would help me. -l, --files-with-matches Suppress normal output; instead print the name of each input file from which output would normally have been printed. The scanning will stop on the first match.
    – Max
    Commented Nov 13, 2018 at 10:08
  • please check my answer and clarify if you really want the colon (:) after the line number
    – user313992
    Commented Nov 13, 2018 at 14:03

2 Answers 2

2
find src/ -type f -name '*.js' -exec grep -Hn -E -- 'filter\(|map\(' {} + |
    awk -F: '{printf "%-100s%-5s%-100s\n", $1, $2, substr($0, length($1) + length($2) + 3)}'

The -H option to grep will cause it to print the filename even when called with a single file as argument. The -type f option to find is needed in order to skip broken links and directories that happen to be named *.js.

Or even simpler, get rid of grep completely (thanks to @don_crissti for the suggestion):

find src/ -type f -name '*.js' -exec awk '/filter\(|map\(/{printf "%-100s%-5s%-100s\n", FILENAME, FNR, $0}' {} +
1
  • Elegant solution, just what I needed. The colon is not necessary.
    – Max
    Commented Nov 13, 2018 at 19:22
0

man makes it a bit unclear. "The scanning will stop on the first match" - indicates that all file names will be printed, but the scanning for the matching word will stop at the first occurence. GNU grep man page clarifies this:

-l
--files-with-matches
Suppress normal output; instead print the name of each input file from which output would normally have been printed. The scanning of each file stops on the first match. (-l is specified by POSIX.)

Here is an example:

$grep -iR Intel * 
2018/jan/cpu.txt:Intel i9 
2018/motherboard.txt:Intel Motherboard 
hardware.txt:Intel Corei7
#the same result as you provided;

$grep -iRl Intel * 
2018/jan/cpu.txt
2018/motherboard.txt
hardware.txt
#the desired result
1
  • Not quite what I wanted. Please scroll the output to the right and you'll se that I also want line number and line of code, but formatted as on the first row.
    – Max
    Commented Nov 13, 2018 at 12:08

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .