How do I select a subset of lines from the history in bash? - linux

Quite often I grep through my bash shell history to find old commands, filepaths, etc. Having identified the history number of interest, I would like to see a few lines of context on either side, i.e. view a subset of history lines. For example:
$ history | grep ifconfig
8408 ifconfig eth0
8572 sudo ifconfig eth0 down
I would like to look at the 5 lines or so either side of line 8572. Obviously knowing the line number I can page through the history with less, but this seems very stupid. As far as I can tell, the manpage doesn't seem to have this information either.
Is there a simple way to retrieve arbitrary lines of history in bash?

grep's -C option provides context. Try:
$ history | grep -C 5 ifconfig

history | grep -C 5 ifconfig

If you only want to see it for specific line numbers, you can also use something like this
history | head -n 120 | tail -n 5
The example prints lines 116 through 120.

history | grep ifconfig -A5 -B5
A = number of lines after the match found by grep
B = number of lines before the match found by grep
You can also change the number of lines from 5 to any number you want.

type ctrl-r, then some characters (interactive searching). More information here.

I type
history | grep " 840"

Related

Counting words in a apropos command

I have this command apropos -l apple. I want to count the word "apple" from the output of the command. I am a beginner in UNIX commands, and have an idea that I have to use grep or wc, but I'm not sure how. Any help would be appreciated.
apropos -l apple | grep -io apple
There are many options within grep that can help you meet your objective and the above is just an example.
Take the output of apropos -l and then pipe through to grep. With grep, we search for all "apple" entries with -i to show any case combinations. We then finally output the generated list through to wc -l to count the lines and therefore the entries,

Show not logged users processes linux bash script

I am doing a bash script and i am essaying to show not logged users processes,which are typically daemon processes, for this,in the exercise, they recommend me:
To process the command line, we will use the cut command, which allows
selecting the different columns of the list through a filter.
I used:
ps -A | grep -v w
ps -A | grep -v who
ps -A | grep -v $USER
but trying all these options all the processes of all users are printed in the output file, and I only want the processes of users who are not logged.
I appreciate your help
Thank you.
grep -v w will remove lines matching the regular expression w (which is simply anything which contains the string w). To run the command w you have to say so; but as hinted in the instructions, you will also need to use cut to post-process the output.
So as not to give the answer away completely, here's rough pseudocode.
w | cut something >tempfile
ps -A | grep -Fvf tempfile
It would be nice if you could pass the post-processed results of w in a pipe, but standard input is already tied to ps -A. If you have a shell which supports process substitution, you can use that.
ps -A | grep -Fvf <(w | cut something)
Unfortunately, the output from w is not properly machine-readable -- you will properly want to cut out the header line(s), too. (On my machine, there are two header lines. Yours might differ.) You'll probably learn a bit of Awk later on in the course, but until then, maybe something like
ps -A | grep -Fvf <(w | tail -n +3 | cut something)
This still doesn't completely handle all possible situations. What if someone's account name is grep?

Getting iwconfig output in fields

I just did an iwconfig 2>/dev/null | hd and an echo $(iwconfig 2>/dev/null) | hd
Both outputs have no clear separation between fields and inner-field spaces… it's all spaces -.^
The man-page didnt bring up any way to set iwconfig's field-separator, so i read the sourcecode and there is none, all is done by concatenating sprintf's.
I've seen a script that froze hell will some awk's just to get some values and that expected the accesspoint at iwconfig | awk 'Access point:/ {print $6}' and as i had to change that for my system to $4 i wonder if gathering all infomation, stuffing it into a clumpsy output, parsing that linewise and regexing thru the lines really is the proper way to do it … is there an alternative to iwconfig that yields the same information as hash with usefull separated fields, names and values?
From the shell , awk or sed may be the only solution. But if you are writing the program in C, you can use the ioctl commands that iwconfig is actually using to print the info you see.
You might also want to give iw a try. iwconifg is being replaced by iw.
You could get the access point mac address with
iwconfig 2>&1 | sed -n -e 's/^.*Access Point: //p'

How to crop(cut) text files based on starting and ending line-numbers in cygwin?

I have few log files around 100MBs each.
Personally I find it cumbersome to deal with such big files. I know that log lines that are interesting to me are only between 200 to 400 lines or so.
What would be a good way to extract relavant log lines from these files ie I just want to pipe the range of line numbers to another file.
For example, the inputs are:
filename: MyHugeLogFile.log
Starting line number: 38438
Ending line number: 39276
Is there a command that I can run in cygwin to cat out only that range in that file? I know that if I can somehow display that range in stdout then I can also pipe to an output file.
Note: Adding Linux tag for more visibility, but I need a solution that might work in cygwin. (Usually linux commands do work in cygwin).
Sounds like a job for sed:
sed -n '8,12p' yourfile
...will send lines 8 through 12 of yourfile to standard out.
If you want to prepend the line number, you may wish to use cat -n first:
cat -n yourfile | sed -n '8,12p'
You can use wc -l to figure out the total # of lines.
You can then combine head and tail to get at the range you want. Let's assume the log is 40,000 lines, you want the last 1562 lines, then of those you want the first 838. So:
tail -1562 MyHugeLogFile.log | head -838 | ....
Or there's probably an easier way using sed or awk.
I saw this thread when I was trying to split a file in files with 100 000 lines. A better solution than sed for that is:
split -l 100000 database.sql database-
It will give files like:
database-aaa
database-aab
database-aac
...
And if you simply want to cut part of a file - say from line 26 to 142 - and input it to a newfile :
cat file-to-cut.txt | sed -n '26,142p' >> new-file.txt
How about this:
$ seq 1 100000 | tail -n +10000 | head -n 10
10000
10001
10002
10003
10004
10005
10006
10007
10008
10009
It uses tail to output from the 10,000th line and onwards and then head to only keep 10 lines.
The same (almost) result with sed:
$ seq 1 100000 | sed -n '10000,10010p'
10000
10001
10002
10003
10004
10005
10006
10007
10008
10009
10010
This one has the advantage of allowing you to input the line range directly.
If you are interested only in the last X lines, you can use the "tail" command like this.
$ tail -n XXXXX yourlogfile.log >> mycroppedfile.txt
This will save the last XXXXX lines of your log file to a new file called "mycroppedfile.txt"
This is an old thread but I was surprised nobody mentioned grep. The -A option allows specifying a number of lines to print after a search match and the -B option includes lines before a match. The following command would output 10 lines before and 10 lines after occurrences of "my search string" in the file "mylogfile.log":
grep -A 10 -B 10 "my search string" mylogfile.log
If there are multiple matches within a large file the output can rapidly get unwieldy. Two helpful options are -n which tells grep to include line numbers and --color which highlights the matched text in the output.
If there is more than file to be searched grep allows multiple files to be listed separated by spaces. Wildcards can also be used. Putting it all together:
grep -A 10 -B 10 -n --color "my search string" *.log someOtherFile.txt

Preserve colouring after piping grep to grep

There is a simlar question in Preserve ls colouring after grep’ing but it annoys me that if you pipe colored grep output into another grep that the coloring is not preserved.
As an example grep --color WORD * | grep -v AVOID does not keep the color of the first output. But for me ls | grep FILE do keep the color, why the difference ?
grep sometimes disables the color output, for example when writing to a pipe. You can override this behavior with grep --color=always
The correct command line would be
grep --color=always WORD * | grep -v AVOID
This is pretty verbose, alternatively you can just add the line
alias cgrep="grep --color=always"
to your .bashrc for example and use cgrep as the colored grep. When redefining grep you might run into trouble with scripts which rely on specific output of grep and don't like ascii escape code.
A word of advice:
When using grep --color=always, the actual strings being passed on to the next pipe will be changed. This can lead to the following situation:
$ grep --color=always -e '1' * | grep -ve '12'
11
12
13
Even though the option -ve '12' should exclude the middle line, it will not because there are color characters between 1 and 2.
The existing answers only address the case when the FIRST command is grep (as asked by the OP, but this problem arises in other situations too).
More general answer
The basic problem is that the command BEFORE | grep, tries to be "smart" by disabling color when it realizes the output is going to a pipe. This is usually what you want so that ANSI escape codes don't interfere with your downstream program.
But if you want colorized output emanating from earlier commands, you need to force color codes to be produced regardless of the output sink. The forcing mechanism is program-specific.
Git: use -c color.status=always
git -c color.status=always status | grep -v .DS_Store
Note: the -c option must come BEFORE the subcommand status.
Others
(this is a community wiki post so feel free to add yours)
Simply repeat the same grep command at the end of your pipe.
grep WORD * | grep -v AVOID | grep -v AVOID2 | grep WORD

Resources