Note
We are no longer accepting new customers or work orders at this time. Thank you for your interest.
In Unix/Linux, there are times when you need to view the middle of a text file. Given a line number, you might want to see 5 or 10 lines of text at that position. Unix/Linux comes with the "head" and "tail" commands, which let you view the beginning or ending of a file - but there's no actual "mid" or "middle" command.
Luckily, you can construct one from these 2 commands.
Figuring Out the Command
Playing around on the command line, you can discover what set of commands, connected with pipes, will give you the output you want. The method I usually use is:
tail -n +linenum filename | head -n numlines
This works because the tail command with a plus ("+") argument says "display the rest of the file, starting on this line number". The head command then takes that text data, and chops it down to only the first so-many lines.
Making It One Command - Easier To Use
If you're going to use this over and over, you don't want to have to remember that pipeline command every time! What a pain.
Luckily there's a few ways you can shorten it in Unix. If you use the csh/tcsh, you can create a 1-line alias. Or you can write a small shell script and put it in your "bin" directory. Either way, it will feel like you created a new Unix command that didn't exist before.
Csh/Tcsh Alias
Here's the alias that creates the "mid" command:
alias mid 'tail -n +\!:1 \!:3* | head -n \!:2'
If you type it into your command line, you can use it until you close that shell. A better idea is to add it to your ~/.tcshrc file (or ~/.cshrc), so that it's always there in every new shell you open, every time you log in.
Shell Script
Alternatively, you can create a shell script called "mid" as a new command. Create a new file, and put this into it:
#!/bin/sh if test $# -lt 2; then echo "$0: insufficient arguments on the command line." >&2 echo "usage: $0 startlinenum numlines [filename]" >&2 exit 1 fi tail -n +$1 $3 | head -n $2 exit $?
You can choose where you put this script - if you have a bin directory in your home directory that's part of your PATH, you can put it there. If you're the root user and want everyone to have access to it, then put it in /usr/local/bin (and make sure that's in everyone's path).
Either way, you need to make sure it's executable by running this command on it once:
chmod +x mid ls -l mid
(that last command will show you the permissions on the script)
Now make sure you can access the script. Type these commands at the command line:
rehash (only needed in csh/tcsh) which mid (you should not get an error)
Using Your New "mid" Command
The syntax is like this:
mid startline numlines filename
I.E.
mid 251 10 biglib.pl
This is so useful when you see error messages with line numbers. You can view the "context" around the error line, with as many lines above/below as you want. You can see just the error on line 489:
mid 489 1 program.c
Or 2 lines above and at least 20 lines below it:
mid 487 25 program.c
Efficiency
Not only does this work, but it's very optimal. Both the head and tail programs will be running at the same time, and when head has seen enough data, it will exit - which will break the pipe - which will terminate the tail command!
This is good when you have a huge text file (let's say 100,000 lines) and you only want to see lines 510-520. The command:
tail -n +510 filename | head -n 11
Will do the trick, and the tail command won't have to read all 100,000 lines the way you'd think it would.
This is one of the differences between true pipes in Unix, and fake pipes in other operating systems like Windows/DOS. With Windows, the first command is expected to run to completion first - reading all 100,000 lines, and outputting nearly that much - before the second command is launched and fed the temporary data.
So How Do Unix Pipes Work?
You don't have to know that to use it, but I'm happy to explain it anyway.
There's no temporary file in Unix the way there would be in Windows. Just a small buffer in RAM memory (about 4KB in size), which the tail and head utilities take turns working with. Tail fills up the buffer with text, and head sucks the data out and works with it; then tail goes again, then head goes again, over and over and over.
When the pipe buffer "fills up", the writer (the tail command) is suspended temporarily ("blocked") until the pipe has more room in it. This gives the head command a chance to get CPU time. So the head command reads from the pipe until it's empty, which causes the head command to suspend temporarily ("blocked") until the pipe has more data in it. Back and forth.
The design is simple and elegant - like many things in Unix.
Related Commands - Gnu Grep
A related command that's really awesome is Gnu Grep (grep or ggrep). It has options that let you see a few lines above and below the matched line! Try this out:
grep -A3 -B3 someword somefile
This means "display 3 lines after, and 3 lines before, every occurrence of the string 'someword' in the file 'somefile'".
If you have any flavor of Linux, your grep should be able to do this. If your OS doesn't understand the -A and -B options, you don't have the Gnu version of Grep. You probably should get it and install it. Gnu utilities like Grep are just the best ones out there.
Old Unix Head/Tail Commands
If you have the older Unix versions of head and tail, they don't accept the '-n' option. So instead you'd use this csh alias:
alias mid 'tail +\!:1 \!:3* | head -\!:2'
and this line in the critical part of the shell script:
tail +$1 $3 | head -$2
Gnu has versions of head, tail, and most other "bin" utilities like those. The source code is freely available for basically every flavor of Unix in the world. You can download the source, compile it and install it, if you don't have them already.
Don't miss the latest unix tips and tricks!
Subscribe to our low-volume mailing list:
Privacy Policy
| Copyright © 2006 - 2010 Keith Smith Internet Marketing LLC, all rights reserved. |
| Problem with this web site? please let us know |