Let's we combine some hints of the solutions just showed.
From Stephane+ Gilles:
grep -E '^.{11,22}John' source.txt | cut -c12-26,44-
# or, if you want only "John " and not Johnson, add a space after John.
grep -E '^.{11,22}John ' source.txt | cut -c12-26,44-
Here you need to use /bin/grep
and also /bin/cut
.
From Gilles + Hauke:
grep -E '^.{11,22}John' source.txt | while read line; do echo "${line:11:14} ${line:43}"; done
Here you need to use /bin/grep
and also echo
.
In modern shell you find echo
like a built-in command so it requires less.
The Hauke's solution is the less expensive in term of installed programs: it requires only echo
(built-in so bash
), but not even /bin/grep
, as wished in the question.
Update Let's we play a little.
In the everyday life we run snippet of code, created on the fly and used maybe nevermore;
not always it results convenient to spend our human time to optimize it or to try different variations...
but semel in anno licet insanire:
on the other hand and with an high probability this was a case-study question
,
maybe even an homework not completely clear. In this optic, and IMHO, all the different approaches and solutions are useful.
We all agree, it seems, that for a big number of lines it is better (faster) to use a compiled program
then a sequence of shell commands. But what is big? I think that numbers (and plots) can fix ideas
better than only words: so let's we see.
Here the recipe: A set of files with a growing number of lines, N,
was prepared. Each line was randomly extracted from the 11 original posted here.
The values of N used are
11 22 55 110 220 550 1100 2200 5500 11000 110000 1100000 11000000
.
The snippet tested are:
- The
Cut+Paste+Grep+Cut
tab=$(printf '\t') ; cut -c12-26 file | paste - file | grep "^[^$tab]*John" | cut -c1-16,60-
- Green
- The
Only Grep
- Blue grep -E '^.{11,22}John' source.txt
. Simply the grep
with no formatted output as asked.
- The
Grep+Cut
- Red [grep -E '^.{11,22}John' source.txt | cut -c12-26,44-
].
- The
Grep+While
- Violet [see above in this answer, the grep before and the while loop].
- The
While loop
- Yellow a full bash solution that do not require grep
For each size of the files and snippet, a number of repetitions, NRep, was made
starting from 400 (for the shorter files) and decreasing with N down to 100,
10, and 1 for the last one.
It was recorded the value of Time per line, Tpl, aka the real time as measured by the built-in function
time
and averaged on NRep and N. Since both Tpl and N span over powers of 10 it was plotted
the common logarithm (to base 10, or the powers of 10). The lines reported are Bezier curves that touch each point.
For large values of N the Time per Line become almost constant. It is the so-called asymptotic behaviour.
As expected, the lesser the compiled program used number, the faster the result.
On the contrary, with small files, the result is the opposite.
The efficiencies of different codes cross each other in a region that (for our example) is between 40 and 140 lines.
Even if it is true that for small files is small even the overall human time used,
the same consideration is not anymore valid when it is needed to work with a big number of little files:
the pure bash code (yellow) that asymptotically is 8.12 times slower than the green one,
and even 157 times slower that the red one (for the 11M lines file it uses 334.56 s. instead of 41.21s of the green and 2.16 of the red)
it is instead respectively 2.16 and 1.58 times faster for the 11 lines one, when it uses 1.20s for 400 repetitions instead of 1.89s of the red or 2.59s of the green.
Conclusion: The more you know, the better you challenge, and check always when you can! :-)
Ps> Similar consideration can be done on the user time and sys time, but with slightly different crossing region.
bash 4.3.11(1)-release
paste (GNU coreutils) 8.21
cut (GNU coreutils) 8.21
grep (GNU grep) 2.16
kernel 3.13.0-24-generic x86_64
grep
for that instead ofawk
. And I doubt thatgrep
alone is capable of that.