Reputation: 45652
I want to run ack or grep on HTML files that often have very long lines. I don't want to see very long lines that wrap repeatedly. But I do want to see just that portion of a long line that surrounds a string that matches the regular expression. How can I get this using any combination of Unix tools?
Upvotes: 134
Views: 62578
Reputation: 383984
bgrep
if lines don't necessarily fit into memory
grep
only works if the lines fit into memory, but bgrep also works on huge lines that don't.
I keep coming back to this random repo from time to time: https://github.com/tmbinc/bgrep Install:
curl -L 'https://github.com/tmbinc/bgrep/raw/master/bgrep.c' | gcc -O2 -x c -o $HOME/.local/bin/bgrep -
Use:
bgrep `printf %s saf | od -t x1 -An -v | tr -d '\n '` myfile.bin
Sample output:
myfile.bin: c80000003
\x02abc
myfile.bin: c80000007
dabc
I have tested it on files that don't fit into memory, and it worked just fine.
I've given further details at: https://unix.stackexchange.com/questions/223078/best-way-to-grep-a-big-binary-file/758528#758528
Upvotes: 0
Reputation: 882
To get characters from 1 to 100.
cut -c 1-100
You might want to base the range off the current terminal, e.g.
cut -c 1-$(tput cols)
Upvotes: 17
Reputation: 11376
grep -oE ".{0,10}error.{0,10}" mylogfile.txt
In the unusual situation where you cannot use -E
, use lowercase -e
instead.
Upvotes: 21
Reputation: 53986
You could use the grep options -oE
, possibly in combination with changing your pattern to ".{0,10}<original pattern>.{0,10}"
in order to see some context around it:
-o, --only-matching Show only the part of a matching line that matches PATTERN. -E, --extended-regexp Interpret pattern as an extended regular expression (i.e., force grep to behave as egrep).
For example (from @Renaud's comment):
grep -oE ".{0,10}mysearchstring.{0,10}" myfile.txt
Alternatively, you could try -c
:
-c, --count Suppress normal output; instead print a count of matching lines for each input file. With the -v, --invert-match option (see below), count non-matching lines.
Upvotes: 127
Reputation: 44019
The Silver Searcher (ag) supports its natively via the --width NUM
option. It will replace the rest of longer lines by [...]
.
Example (truncate after 120 characters):
$ ag --width 120 '@patternfly'
...
1:{"version":3,"file":"react-icons.js","sources":["../../node_modules/@patternfly/ [...]
In ack3, a similar feature is planned but currently not implemented.
Upvotes: 2
Reputation: 1170
ag
can also take the regex trick, if you prefer it:
ag --column -o ".{0,20}error.{0,20}"
Upvotes: 0
Reputation: 884
Here's what I do:
function grep () {
tput rmam;
command grep "$@";
tput smam;
}
In my .bash_profile, I override grep so that it automatically runs tput rmam
before and tput smam
after, which disabled wrapping and then re-enables it.
Upvotes: 1
Reputation: 199
I put the following into my .bashrc
:
grepl() {
$(which grep) --color=always $@ | less -RS
}
You can then use grepl
on the command line with any arguments that are available for grep
. Use the arrow keys to see the tail of longer lines. Use q
to quit.
Explanation:
grepl() {
: Define a new function that will be available in every (new) bash console.$(which grep)
: Get the full path of grep
. (Ubuntu defines an alias for grep
that is equivalent to grep --color=auto
. We don't want that alias but the original grep
.)--color=always
: Colorize the output. (--color=auto
from the alias won't work since grep
detects that the output is put into a pipe and won't color it then.)$@
: Put all arguments given to the grepl
function here.less
: Display the lines using less
-R
: Show colorsS
: Don't break long linesUpvotes: 3
Reputation: 93755
Pipe your results thru cut
. I'm also considering adding a --cut
switch so you could say --cut=80
and only get 80 columns.
Upvotes: 58
Reputation: 9370
Taken from: http://www.topbug.net/blog/2016/08/18/truncate-long-matching-lines-of-grep-a-solution-that-preserves-color/
The suggested approach ".{0,10}<original pattern>.{0,10}"
is perfectly good except for that the highlighting color is often messed up. I've created a script with a similar output but the color is also preserved:
#!/bin/bash
# Usage:
# grepl PATTERN [FILE]
# how many characters around the searching keyword should be shown?
context_length=10
# What is the length of the control character for the color before and after the
# matching string?
# This is mostly determined by the environmental variable GREP_COLORS.
control_length_before=$(($(echo a | grep --color=always a | cut -d a -f '1' | wc -c)-1))
control_length_after=$(($(echo a | grep --color=always a | cut -d a -f '2' | wc -c)-1))
grep -E --color=always "$1" $2 |
grep --color=none -oE \
".{0,$(($control_length_before + $context_length))}$1.{0,$(($control_length_after + $context_length))}"
Assuming the script is saved as grepl
, then grepl pattern file_with_long_lines
should display the matching lines but with only 10 characters around the matching string.
Upvotes: 2
Reputation: 4385
You could use less as a pager for ack and chop long lines: ack --pager="less -S"
This retains the long line but leaves it on one line instead of wrapping. To see more of the line, scroll left/right in less with the arrow keys.
I have the following alias setup for ack to do this:
alias ick='ack -i --pager="less -R -S"'
Upvotes: 29