On most UNIX/Linux systems, you can read the header like this:
hexdump -e '80/1 "%_p" "\n"' myfile.fits
which only half the solution; the other half is getting the actual data out.
If I resort to writing a little python, I can get the output I want. For example, using this command:
hexdump -e '"%_ad\t" 80/1 "%_p" "\n"' astlimits.fits | less
I can look through the FITS file, and find the byte number of the start of the data I am interested in. (The %_ad starts each line of output with a byte number, the %_p prints each printable character and replaces non-printable ones with a "." Because FITS data must begin at an integer multiple of 2880, the data will start at the start of a line when broken into 80 byte lines.) I can read off the number of rows from the NAXIS2 header keyword of the HDU I am interested in, and the types of each column from the TFROMx keywords.
So, if the data I want starts at byte 5760, the number of rows 5730 (close by coincidence only), and the bytes per row 42 (from NAXIS1), I can use the following python to extract the table I want:
python -c 'import struct
> f = open("astlimits.fits")
> f.seek(5760)
> for i in range(5730): print "\t".join(map(str,struct.unpack(">hhhddhhiiii",f.read(42))))
Less compactly but more readably, this is like running this python script:
import struct
data_start_byte = 5760
num_bytes_in_row = 42 # NAXIS1 from header
num_rows = 5730 # NAXIS2 from header
f = open("astlimits.fits")
f.seek(data_start_byte)
for r in range(num_rows):
row_bytes = f.read(num_bytes_in_row)
row_values = struct.unpack(">hhhddhhiiii", row_bytes)
row_strings = [str(v) for v in row_values]
print "\t".join(row_strings)
If I used a big endian machine, I could do all of this with another hexdump statement. Unfortunately, hexdump won't change endian-ness.
The hardest thing here is remembering how the type codes used in the FITS TFORM values map to the types codes in the first argument of struct.unpack.
But, what I really want is something comparable to hexdump in simplicity. 373