Linux - GeneralThis Linux forum is for general Linux questions and discussion.
If it is Linux Related and doesn't seem to fit in any other forum then this is the place.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
Dear Scripting Gurus,
I have a problem creating a new script, which gets some specific information from a logs file, the problem is that I want to grep all the lines in the file until a specific pattern is found.
so for example if the file has these lines:
Suse
Fedora
Ubunto
Gentoo
Mandrake
Freespire
Red hat
=================
I want the script to scan the file and print all the lines until it finds Mandrake and stops, which would give in the above example:
Sed and awk are indeed very nice and powerful tools for everyday use and for using in shell scripts.
There's a lot of information on-line for both. If you are interested in printed information take a look at O'Reilly's sed&awk book.
The -n is needed to suppress the normal output of sed (try not using it), only what is found needs to be printed and that is done by the p at the end.
the 1,/Gentoo/ part is the address range. This states: start at line 1 all the way up to and including Gentoo. The last part must be between forward slashes to indicate that this is a regular expression, not an actual line number. A 'normal' address range looks like this: 3,12 which indicates lines 3 to 12 (including).
The main thing is that you can use regular expression(s) as address indicators. The next example will print all between (and including) Ubunto and Freespire:
sed -n '/Ubunto/,/Freespire/p' infile
The -e option is not used in my example, but you can string sed statements together:
sed -e 's/o/XX/' -e 's/a/YY/' infile is the same as sed 's/o/XX/' infile | sed 's/a/YY/'. The first one being better, it's a lot more resource friendly.
Hi Drunna,
How are you buddy, here's another challenge I found creating my script, my log file contains Timestamps, what I want to do is to grep a specific number of lines around the - for example - Gentoo line,
In another way, I want to have the chunk of lines around the line I want (which is included of course) , a period of time in my case ...
This is indeed a challenge, but no fear sed is here
Code:
#!/bin/bash
# -------------------------------------------------------------------------- #
# prints out 4 lines around pattern
# -------------------------------------------------------------------------- #
case $# in
2);;
*|1) echo "Usage: $0 pattern <infile>";exit;;
esac;
infile=$2
sed -n '
'/$1/' !{
# does not match - add this line to the hold space
H
# bring it back into the pattern space
x
# Two lines would look like .*\n.*
# Three lines look like .*\n.*\n.*
# Delete extra lines - keep two
s/^.*\n\(.*\n.*\)$/\1/
# now put the two lines (at most) into
# the hold buffer again
x
}
'/$1/' {
# matches - append the current line
H
# get the next line
n
# matches - append the current line
H
# get the next line
n
# append that one also
H
# bring it back, but keep the current line in
# the hold buffer. This is the line after the pattern,
# and we want to place it in hold in case the next line
# has the desired pattern
x
# print the all lines
p
# add the mark
a\
---
}' $infile
# -------------------------------------------------------------------------- #
# End
There will be a mark (---) printed at the end of each hit. Just remove the a\ and the --- from the script if that is not needed.
I included as much comments as possible. Here's the same script, without all the comments:
Code:
#!/bin/bash
# -------------------------------------------------------------------------- #
# Prints out 4 lines around pattern.
# -------------------------------------------------------------------------- #
case $# in
2);;
*|1) echo "Usage: $0 pattern <infile>";exit;;
esac;
infile=$2
sed -n '
'/$1/' !{
H
x
H
x
s/^.*\n\(.*\n.*\)$/\1/
x
}
'/$1/' {
H
n
H
x
p
a\
---
}' $infile
# -------------------------------------------------------------------------- #
# End
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.