2

I have a very huge file and need to look at a few characters in the middle of some huge line.

Is there a way to show easily characters from n1 position to n2 position in line number l in some file?

I think there should be some way to do it with sed, just cannot find corresponding option.

fedorqui
  • 275,237
  • 103
  • 548
  • 598
Maxim Galushka
  • 397
  • 1
  • 5
  • 22

3 Answers3

4

You better use awk:

awk 'NR==line_number {print substr($0,start_position,num_of_characters_to_show)}' file

For example, print 5 characters starting from the 2nd character in the line 2:

$ cat a
1234567890
abcdefghij
$ awk 'NR==2 {print substr($0,2,5)}' a
bcdef

If you really need to use sed, you can use something like:

$ sed -rn '2{s/^.{1}(.{5}).*$/\1/;p}' a
bcdef

This matches 2-1=1 digits after the beginning of the line and then catches 5 to print them back. And all of this is done just in the line 2, so we use -n to prevent the default print of the line.

Maxim Galushka
  • 397
  • 1
  • 5
  • 22
fedorqui
  • 275,237
  • 103
  • 548
  • 598
3

The elegance of UNIX has always lain in its ability to string together relatively simple programs into pipelines to achieve complexity. You can do a sed-only solution but it's not likely to be as readable as a pipeline.

To that end, you can use a combination of sed to get a specific line and cut to get character positions on that line:

pax> echo '12345
...> abcde
...> fghij' | sed -n 2p | cut -c2-4
bcd

If you just want to use a single tool, awk can do it:

pax> echo '12345
...> abcde
...> fghij' | awk 'NR==2{print substr($0,2,3);exit}'
bcd

So can Perl:

pax> echo '12345
...> abcde
...> fghij' | perl -ne 'if($.==2){print substr($_,1,3); exit}'

In both those cases, it exits after the relevant line to avoid processing the rest of the file.

paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
  • 1
    You will probably also need to pipe to `tail` to get the exact line number. For example, to get the 25th line you need `head -n 25 | tail -n 1` – fedorqui May 06 '15 at 10:02
0

One solution using only , that insert newlines characters just before and after the substring and uses them as flags to remove all content not between them, like:

sed -n '2 { s/.\{5\}/&\n/; s/.\{2\}/&\n/; s/[^\n]*\n//; s/\n.*//; p; q }' infile

Assuming infile like:

1234567890
abcdefghij

It yields:

cde

Not that range is from 2 to 5 but start counting from zero and it excludes the end (so characters 2, 3 and 4). You can handle with it or do some arithmetic just before the command.

Birei
  • 35,723
  • 2
  • 77
  • 82