ok, this is driving me crazy! I am trying to grep some info from a log file and add it to a summary in a email notification.

from log:

2019/07/22 11:36:03 [14396] Number of created files: 3 (reg: 2, dir: 1)

Now I want the print to be only the numbers at the end, 3, 2, 1 or maybe the entire last part 3 (reg: 2, dir: 1)

I have tried different things and this is the closest I got, but it only prints the number 3 and not the rest of the info I want.

nf=$(grep -o 'created files:' $logfile) | cut -d\   -f3)

Is this possible at all?


Ok, so I got it working using nf=$(grep -Po 'created files: \K.*' "$logfile")

In my summary I add $nf to get the output like this Created $nf new files giving me this result

Created 3 (reg: 2, dir: 1) new files

Now, can I somehow split it up even more so my result will be something like this? Created 1 directory and 2 files

Maybe using two separate grep commands to output the different variables, one for dir and one for reg on that line?

  • That last command should have grep -o 'created files:.*' or grep 'created files:' since grep -o with a constant string pattern would only print that string. – ilkkachu Jul 22 '19 at 10:38

If your grep supports perl-compatible regular expressions (PCRE):

$ grep -Po 'created files: \K.*' "$logfile"
3 (reg: 2, dir: 1)

To save the numbers into a bash array:

$ numbers=( $(grep -o 'created files:.*' "$logfile" | grep -o '[0-9]\+') )
$ echo ${numbers[@]}
3 2 1
$ echo "${numbers[0]}, ${numbers[1]}, ${numbers[2]}"
3, 2, 1
  • The first part worked. Can you please explain what the different part in that command does? – prophetse7en Jul 22 '19 at 10:43
  • With the -P option you can use \K to match the whole pattern, but created files: is not included in the output. Only everything after that is in the output (.*). – Freddy Jul 22 '19 at 11:18
  • What's the output of the second example? Are you using a different shell? – Freddy Jul 22 '19 at 12:22

Perl to the rescue:

$ perl -ne 'print "$1 $2 $3\n" if /created files: (\d+) \(reg: (\d+), dir: (\d+)\)/' < "$logfile"
3 2 1

or with sed:

$ sed -nEe 's/.*created files: ([0-9]+) \(reg: ([0-9]+), dir: ([0-9]+)\)/\1 \2 \3/p' "$logfile"
3 2 1

Both do mainly the same thing: match the whole ending part of the line (not just created files), but capture (with (...)) the numbers and print them or replace the line with them.


To fix your command:

  • Add .* to the pattern to include the rest of the line in your grep output.
  • Use -f3- to select all fields from 3rd to the end.


grep -o 'created files: .*' "$logfile" | cut -d\  -f3-
  • 1
    ok, so f3 prints only field3, while -f3- prints field 3 and to the end of the line? – prophetse7en Jul 22 '19 at 11:33
  • exactly! you can use e.g. -f3-6 to select fields 3 to 6, but if you omit the 6, it just selects all fields til the end. – pLumo Jul 22 '19 at 11:41

Using cut to extract all fields after 3:

grep -o 'created files:' $logfile | cut -d" " -f3-
  • I tried this but it dont give any output at all – prophetse7en Jul 22 '19 at 10:35

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.