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?
-
2What's `ack`? Is it a command you use when you don't like something? Something like `ack file_with_long_lines | grep pattern`? :-) – Alok Singhal Jan 09 '10 at 20:27
-
8@Alok `ack` (known as `ack-grep` on Debian) is `grep` on steroids. It also has the `--thpppt` option (not kidding). http://betterthangrep.com/ – ZoogieZork Jan 09 '10 at 20:33
-
Thanks. I learned something today. – Alok Singhal Jan 09 '10 at 20:37
-
1While the `--thpppt` feature is somewhat controversial, the key advantage appears to be that you can use Perl regexes directly, not some crazy `[[:space:]]` and characters like `{`, `[`, etc. changing meaning with the `-e` and `-E` switches in a way that's impossible to remember. – Evgeni Sergeev Jan 03 '14 at 07:03
-
Similar: https://unix.stackexchange.com/q/163726 and https://stackoverflow.com/q/8101701 – sondra.kinsey Sep 15 '19 at 17:27
-
I use `grep --color=always | less -S -R`. Then, type `-R` to unfold/fold the lines. – Jérôme Pouiller Aug 11 '20 at 07:39
10 Answers
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.
-
52
-
17you should change the answer to add -E option as shown by @Renaud (extended pattern option), or the proposed pattern for extending context wont work. – kriss Oct 28 '13 at 13:30
-
1Not that necessary maybe but here's an example: `$ echo "eeeeeeeeeeeeeeeeeeeeqqqqqqqqqqqqqqqqqqqqMYSTRINGwwwwwwwwwwwwwwwwwwwwrrrrrrrrrrrrrrrrrrrrr" > fileonelongline.txt && grep -oE ".{0,20}MYSTRING.{0,20}" ./fileonelongline.txt ` prints `qqqqqqqqqqqqqqqqqqqqMYSTRINGwwwwwwwwwwwwwwwwwwww` – Ulises Layera Nov 21 '18 at 17:30
-
1This works well; but notable downside is that when using, e.g., `oE ".{0,20}mysearchstring.{0,20}"`, you lose the highlighting of the inner "original" string against the context, because the whole thing becomes the search pattern. Would love to find a way to keep some non-highlighted context around the search results, for much easier visual scanning and result interpretation. – Aaron Wallentine Sep 18 '20 at 05:55
-
3Oh, here's a solution to the highlighting problem caused by using the `-oE ".{0,x}foo.{0,x}"` approach (where `x` is the number of characters of context) -- append ` | grep foo ` to the end. Works for either ack or grep solutions. More solutions also here: https://unix.stackexchange.com/questions/163726/limit-grep-context-to-n-characters-on-line – Aaron Wallentine Sep 18 '20 at 06:11
Pipe your results thru cut
. I'm also considering adding a --cut
switch so you could say --cut=80
and only get 80 columns.

- 9,608
- 6
- 34
- 56

- 91,102
- 13
- 100
- 152
-
8
-
3FWIW I appended `| cut=c1-120` to the grep, worked for me (though don't know how to cut around matched text) – Jake Rayson Dec 08 '11 at 17:06
-
35``| cut=c1-120`` didn't work for me, I needed to do ``| cut -c1-120`` – Ken Cochrane Mar 09 '12 at 15:05
-
2I think @edib is accurate in syntax `| cut -c 1-100` https://stackoverflow.com/a/48954102/1815624 – CrandellWS Oct 23 '18 at 16:30
-
2
-
@naught101 You can submit it as an issue https://github.com/beyondgrep/ack3/issues Remember that ack also runs on Windows and I don't know that if they have `$COLUMNS` – Andy Lester Mar 08 '19 at 19:50
-
Existing feature request: https://github.com/beyondgrep/ack3/issues/234 – cweiske Oct 22 '22 at 08:33
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"'

- 4,155
- 7
- 29
- 31
-
2Please note that you can put that `--pager` command in your ~/.ackrc file, if you always want to use it. – Andy Lester Feb 05 '14 at 02:28
-
This sounds like the best solution by far to this problem that bugs me a lot. I wish I knew how to use `ack`. – Brian Peterson Mar 17 '15 at 06:57
-
@BrianPeterson `ack` is pretty much just like `grep`, only simpler in the most common cases – Aaron Wallentine Sep 18 '20 at 05:51
grep -oE ".{0,10}error.{0,10}" mylogfile.txt
In the unusual situation where you cannot use -E
, use lowercase -e
instead.

- 1,189
- 1
- 12
- 26

- 9,922
- 3
- 44
- 62
-
2Do no use backslashes - `grep -oE ".{0,10}error.{0,10}" mylogfile.txt` - at least in Z zhell – Aurelijus Rozenas Apr 26 '21 at 04:47
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)

- 42,413
- 44
- 197
- 320

- 812
- 1
- 11
- 20
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.

- 46,058
- 19
- 106
- 116

- 8,018
- 2
- 41
- 69
-
Works, but outputs trailing junk for me, like this: ^\[\[?62;9;c. I haven't tried debugging because [@Jonah Braun's answer](https://stackoverflow.com/a/11038776) satisfied me. – sondra.kinsey Sep 15 '18 at 21:18
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 ofgrep
. (Ubuntu defines an alias forgrep
that is equivalent togrep --color=auto
. We don't want that alias but the originalgrep
.)--color=always
: Colorize the output. (--color=auto
from the alias won't work sincegrep
detects that the output is put into a pipe and won't color it then.)$@
: Put all arguments given to thegrepl
function here.less
: Display the lines usingless
-R
: Show colorsS
: Don't break long lines

- 179
- 1
- 5
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.

- 41,306
- 31
- 146
- 239
-
but in `ag`, the width "begins" with first character, so this doesn't quite work when the string is in the middle of a very long line – Paul Feb 10 '23 at 01:17
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.

- 814
- 9
- 18
-
That is a nice alternative - except if the actual match is then out of screen... – xeruf May 14 '20 at 19:39
ag
can also take the regex trick, if you prefer it:
ag --column -o ".{0,20}error.{0,20}"

- 941
- 9
- 19