How to find lines containing a string in linux
The usual way to do this is with grep
, which uses a regex pattern to match lines:
grep 'pattern' file
Each line which matches the pattern will be output. If you want to search for fixed strings only, use grep -F 'pattern' file
. fgrep
is shorthand for grep -F
.
You can also use sed
:
sed -n '/pattern/p' file
Or awk
:
awk '/pattern/' file
How to find all files containing specific text (string) on Linux?
Do the following:
grep -rnw '/path/to/somewhere/' -e 'pattern'
-r
or-R
is recursive,-n
is line number, and-w
stands for match the whole word.-l
(lower-case L) can be added to just give the file name of matching files.-e
is the pattern used during the search
Along with these, --exclude
, --include
, --exclude-dir
flags could be used for efficient searching:
This will only search through those files which have .c or .h extensions:
grep --include=\*.{c,h} -rnw '/path/to/somewhere/' -e "pattern"
This will exclude searching all the files ending with .o extension:
grep --exclude=\*.o -rnw '/path/to/somewhere/' -e "pattern"
For directories it's possible to exclude one or more directories using the
--exclude-dir
parameter. For example, this will exclude the dirsdir1/
,dir2/
and all of them matching*.dst/
:grep --exclude-dir={dir1,dir2,*.dst} -rnw '/path/to/search/' -e "pattern"
This works very well for me, to achieve almost the same purpose like yours.
For more options, see man grep
.
Using grep to find lines that each contain ALL search strings
This question specifically asks about grep
, but really sed
or awk
are much cleaner for 'a AND b'-style matches, see How to run grep with multiple AND patterns?
This answer covers how to use grep
to match all lines which match all inputs - my other answer covers matching any input.
Note that grep
is more powerful than simple word-matching, it can match arbitrary patterns, including multiple words.
Consider the following simplified version of the example you provide:
$ cat file
{"id": 2796, "some_model": "Profile", "was_deleted": false}
{"id": 2797, "some_model": "Profile", "was_deleted": true}
{"id": 2798, "some_model": "Another", "was_deleted": false}
You could find item 2796 like so:
$ grep '"\?id"\? *: *2796 *,\?' file
{"id": 2796, "some_model": "Profile", "was_deleted": false}
Or find all non-deleted items:
$ grep '"\?was_deleted"\? *: *false *[,}]' file
{"id": 2796, "some_model": "Profile", "was_deleted": false}
{"id": 2798, "some_model": "Another", "was_deleted": false}
You can even combine the two, to only get item 2796 if it's not deleted (change false
to true
and the line no longer matches):
$ grep '"\?id"\? *: *2796 *,\?.*"\?was_deleted"\? *: *false *[,}]' file
{"id": 2796, "some_model": "Profile", "was_deleted": false}
Or roughly equivalent, using the grep-piping syntax you use above:
$ grep '"\?id"\? *: *2796 *,\?' file | grep '"\?was_deleted"\? *: *false *[,}]'
{"id": 2796, "some_model": "Profile", "was_deleted": false}
These examples hopefully look tricky to get right, because this is not a good idea!
The data you're working with looks to be JSON, a structured data format which grep is not well suited for processing. Valid JSON could be split across multiple lines or have fields in arbitrary order, which will break the above patterns. Not to mention arbitrary white-space (*
), semi-optional quotes ("\?
), and end of field vs. end of object markers ([,}]
) which the above patterns should handle, but are easy to get wrong.
If you are trying to query JSON data, you need a JSON parser, which grep is not. http://www.json.org/ offers links to several popular JSON parsers in many languages, see if any of those will suite your needs. You will have much better success with a real tool than trying to construct complicated regular expressions.
Use grep to find lines containing a string, but not starting with another string
grep -i "session" php.ini | grep -vx ';.*'
Should work
-v is 'invert match', so only lines that don't match are displayed
-x is whole line match
How to find line followed by known string in bash
grep
lets you print context along with matched line(s). Then you just need to ignore the matched line.
echo "$MyString" | grep -B1 String_I_know | head -1
How to grep for lines which contain particular words in a log file?
If you store your patterns in a file, one per line, you can use grep -f file-with-patterns file-to-search.log
From the man page:
-f FILE, --file=FILE
Obtain patterns from FILE, one per line. The empty file
contains zero patterns, and therefore matches nothing. (-f is
specified by POSIX.)
Edit 2018:
Since I wrote this, I have become aware of the following interesting edge cases:
- You can read the list of patterns from pipe using
-f -
(if you don't need stdin, i.e. you specified files on grep's command line) or-f <()
(in any case) grep
's performance starts to fail badly if hundreds of patterns are passed. If your use case is that insane, consider generating and immediately executing ased
(or some other language) script, although this could potentially have problems with overlapping patterns.
How to use sed to find lines with a specific string and output to new file
Using sed
Observe that the following returns nothing:
$ sed -n '/[0-9]{2} install/p' file
But, this works:
$ sed -n '/[0-9]\{2\} install/p' file
2016-05-04 07:38:46 install libcairomm
The issue is that, in sed's default basic regular expressions, {
and }
are treated as ordinary characters. To make them special, they must be escaped with a backslash.
Alternatively, one can specify -E
so that sed
uses the more modern Extended Regular Expressions:
$ sed -En '/[0-9]{2} install/p' file
2016-05-04 07:38:46 install libcairomm
Saving to file
To save the output in a file, instead of displaying it in the terminal, add back the redirection > new.txt
:
sed -n '/[0-9]\{2\} install/p' file > new.txt
Or:
sed -En '/[0-9]{2} install/p' file > new.txt
Compatibility
On very old versions of GNU sed, one cannot use -E
. One must use -r
instead:
sed -rn '/[0-9]{2} install/p' file > new.txt
Using grep
This task does not require sed's many advanced features. grep
is sufficient:
$ grep -E '[0-9]{2} install' file
2016-05-04 07:38:46 install libcairomm
Or:
grep -E '[0-9]{2} install' file >new.txt
Find lines that contain certain text, and print what follows that text
You can just swap your grep
with awk
to get subset of line you're looking for:
tail -f /var/log/hive/hiveserver2.log |
awk -F "Parsing command: " '{print $2}'
SELECT * from table
-F "Parsing command: "
makes "Parsing command: "
field separator for awk
command and $2
gives as substring after this marker.
Related Topics
Linux Free Shows High Memory Usage But Top Does Not
Append Line to /Etc/Hosts File with Shell Script
Linux Script with Curl to Check Webservice Is Up
How to Fetch Java Version Using Single Line Command in Linux
Bashrc Not Loading Until Run Bash Command
Linux - Yum Install Gcc - Missing Kernel-Headers
How to Automatically Pipe to Less If the Result Is More Than a Page on My Shell
Running as a Host User Within a Docker Container
How to Remove Jenkins Completely from Linux
What Does "Soft/Hard Nofile" Mean on Linux
How to Pipe the Results of 'Find' to Mv in Linux
How to Resume Interrupted Download Automatically in Curl
How to Copy File from a Vagrant MAChine to Localhost
How to Pipe Output from Grep to Cp
Should I Put Trailing Slash After Source and Destination When Copy Folders
How to Write Non-Ascii Characters Using Echo
Storing & Accessing Up to 10 Million Files in Linux
Jmeter - Loopback Address Error When Launching Jmeter-Server on Linux