8

I would like to print the character at a given position using only the command line. E.g.:

<command> 5

Would output a if the 5th char of that file was a.

Since I am dealing with big files, ideally this would be able to handle big files.

4

With sed:

$ echo 12345 | sed 's/.\{4\}\(.\).*/\1/;q'
5
$ echo 1234ắ | sed 's/.\{4\}\(.\).*/\1/;q'
ắ

Note that sed will fail to produce output if you input contain invalid multi-byte characters in current locale. You can use LC_ALL=C if you work with single byte characters only.

With ASCII file, you can also use dd:

$ echo 12345 | dd bs=1 skip=4 count=1 2>/dev/null
5
  • 1
    Is there any solution that doesn't involve having to pipe the input? Otherwise it will be slow in bit files no? – testTester Apr 16 '16 at 9:00
  • 1
    @testTester: Just use your file as operand to the command sed 's/.\{4\}\(.\).*/\1/;q' file – cuonglm Apr 16 '16 at 9:01
7

If you want the 5th byte, counting from 1:

dd ibs=1 skip=4 count=1

or

tail -c +5 | head -c 1

Note that tail counts from 1, so given a file containing abcdefg, this prints e.

dd and tail -c are in POSIX. head -c is common, but isn't in POSIX; it's in GNU coreutils, BusyBox, FreeBSD and NetBSd and but not in OpenBSD or Solaris.

  • It's probably worth mentioning that in their current form, these commands won't do anything. You'll either need to add a filename parameter on to the commands or pipe input into them. e.g.: cat file | tail -c +5 | head -c 1 – rinogo Apr 6 '18 at 15:14
  • 1
    @rinogo Both commands read from standard input and write to standard output. – Gilles Apr 6 '18 at 17:08
  • 1
    Indeed! My aim was to help those new to Unix understand how to get data into the commands. – rinogo Apr 6 '18 at 17:10
2

Or using (gnu)grep:

grep -zoP '.{4}\K.'   file

(-z was used to deal with \n before the 5th char)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.