I need to determine if a file contains a certain regex at a certain line and to return true (exit 0) if found, and otherwise false. Maybe I'm overthinking this, but my attempts proved a tad unwieldy. I have a solution, but I'm looking for maybe others that I hadn't thought of. I could use perl, but I'm hoping to keep this "lightweight" as possible as it runs during a puppet execution cycle.
The problem is common enough: in RHEL6, screen was packaged in a way that limited the terminal width to 80 characters, unless you un-comment the line at 132. This command checks to see if that line has already been fixed:
awk 'NR==132 && /^#termcapinfo[[:space:]]*xterm Z0=/ {x=1;nextfile} END {exit 1-x}' /etc/screenrc
Note: if the file has fewer that 132 lines, it must exit with false.
I thought sed
would be of help here, but apparently then you have to do weird tricks like null-substitutions and branches. Still, I'd like to see a sed solution just to learn. And maybe there is something else I overlooked.
EDIT 1: Added nextfile
to my awk solution
EDIT 2: Benchmarks EDIT 3: Different host (idle). EDIT 4: mistakenly used Gile's awk time for optimized-per's run. EDIT 5: new bench
Benchmarks
First, note: wc -l /etc/screenrc
is 216
.
50k iterations when line not present, measured in wall-time:
- Null-op: 0.545s
- My original awk solution: 58.417
- My edited awk solution (with nextfile): 58.364s
- Giles' awk solution: 57.578s
- Optimized perl solution 90.352s Doh!
Sed 132{p;q}|grep -q ...
solution: 61.259s- Cuonglm's
tail | head | grep -q
: 70.418s Ouch! - Don_chrissti's
head -nX |head -n1|grep -q
: 116.9s Brrrrp! - Terdon's double-grep solution: 65.127s
- John1024's sed solution: 45.764s
Thank you John and thank you sed! I am honestly surprised perl was on-par here. Perl loads in a bunch of shared libraries on startup, but as long as the OS is caching them all, it comes down to the parser and byte-coder. In the distant past (perl 5.2?) I found it was slower by 20%. Perl was slower as I originally expected but appeared to be better due to a copy/paste error on my part.
Benchmarks Part 2
The biggest configuration file which has practical value is /etc/services
. So I've re-run these benches for this file and where the line to be changed is 2/3rds in the file. Total lines is 1100, so I picked 7220 and modified the regex accordingly (so that in one case it fails, in another it succeeds; for the bench it always fails).
- John's sed solution: 121.4s
- Chrissti's
{head;head}|grep
solution: 138.341s - Counglm's
tail|head|grep
solution: 77.948s - My awk solution: 175.5s
perl
isn't lightweight? Also - can you give an example of the line you're trying to match? – Sobrique Sep 03 '15 at 09:08perl -ne '$x=/^termcapinfo[[:space:]]*xterm Z0=/,break if $.==132; END{ exit 1-$x }' /etc/screenrc
– Otheus Sep 03 '15 at 14:37head; head
solution too ? I'm just curious how fast it runs with your test file there... – don_crissti Sep 03 '15 at 17:09