I want to search for a value in the VASP OUTCAR
file i.e the format of the line should be
Volume of Typ 1: 98.5 %
What command line should I type in OUTCAR
to go for a specific line or word?
Matter Modeling Stack Exchange is a question and answer site for materials modelers and data scientists. It only takes a minute to sign up.
Sign up to join this communityI want to search for a value in the VASP OUTCAR
file i.e the format of the line should be
Volume of Typ 1: 98.5 %
What command line should I type in OUTCAR
to go for a specific line or word?
The OUTCAR
is a text file. Therefore, you can use the grep
command to grab what you want to search for.
Print the current line:
grep "key_information_string" OUTCAR
Print more lines below the current line:
grep "key_information_string" OUTCAR -A n
Print more lines above the current line:
grep "key_information_string" OUTCAR -B n
Here $n$ represents the number of lines you want to print, such as 5.
grep
here: mattermodeling.stackexchange.com/a/2416/5
$\endgroup$
Mar 22, 2021 at 16:54
n
is to be substituted with the number of lines.
$\endgroup$
Use rg
If you have a significant size file or file(s) to search, do yourself a favor and choose one of the many significantly faster alternatives to grep
, the de facto fastest being ripgrep
.
Specific values
# literal string
rg <options> 'Volume of Typ 1: 98.5 %' path/to/file/or/directory
# any value for the key
rg <options> 'Volume of Typ 1:' path/to/file/or/directory
# any numeric value
rg <options> 'Volume of Typ 1:\s*\d+\.?\d*' path/to/file/or/directory
# any numeric percentage
rg <options> 'Volume of Typ 1:\s*\d+\.?\d*\s%' path/to/file/or/directory
Where <options>
are any additional parameters you want to pass (may be omitted).
The path
argument may be omitted as well, it defaults to the current working directory.
Obviously, you could make the search parameter for the key a pattern too.
N.B. The syntax is the same for grep
(or ag
, or the like).
Selection
If you wanted to select the values only (as in strip the key and unit / suffix), sed
is an option:
cat path/to/file | sed -en 's!^Volume of Typ\s*1:\s*\([0-9]*\.[0-9]*\).*$!\1!gp'
At this point, you've got a list of line-terminated, matched values on your screen.
Neato, no more noise!
Next
Other than looking at the output on screen, you could:
<previous_command> > path/to/values.csv
<previous_command> | awk '{print NR " " $0}' | gnuplot -p -e "plot '<cat'"
Typ n
type number to plot on the x-axis, instead of the running index NR
.)Narrower conditions are obviously possible.
Tips
'
strings make regexes in the shell significantly easier to type.sed
than the often cited /
, !
for instance.References
Bonus: sed
breakdown
cat path/to/file | sed -en 's!^Volume of Typ\s*1:\s*\([0-9]*\.[0-9]*\).*$!\1!gp'
cat
1 reads the file from disk and prints its contents to stdout
|
is a pipesed
is a stream editor:
-e
flag isn't strictly necessary, it's just there to allow for possibly multiple "script" inputs at once-n
suppresses output (get rid of non-matching lines)s!<search_pattern>!<replacement>!<flags>
<search_pattern>
^
beginning of the lineVolume of Typ
literal string to be matched\s*
any number of whitespaces:
literal string to be matched\s*
any number of whitespaces(...)
group that may be referenced (no effect on matching)[0-9]*
any number of digits (character class with a *
quantifier)\.
an escaped, literal period (.
has a logical meaning in regular expressions)<replacement>
is \1
, a backreference to the group (...)
above<flags>
are:
g
apply globally (you want more than one match)p
print matches to stdout
(we had negated all output with -n
earlier to get rid of non-matching lines)1 For the sake of completeness: cat
's actual purpose is text (or file) concatenation and it takes any number of arguments. Most of its invocations in its lifetime have certainly been with one argument to read a file.
To search for all the strings in all of the files in current folder you would use simply:
grep string *
Or in subfolder:
grep string subfolder/*
Unfortunately recursion is not possible so you can only search one folder at the time.
-r
flag.
$\endgroup$
grep
so that it targets a speciffic file, but you can target multiple files like I did here. I did not know about the recursion!? How can this be done? Can you give me an excakmple here in the comments?
$\endgroup$
grep -R "some string" ./
, it will search for "some string" in every file in every subdirectory of ./ . Using -R
, rather than -r
, even allows it to search through symbolic links. This is at least the case for GNU grep version 2.20.
$\endgroup$
If you open with vim, you can find it by following command line.
vim OUTCAR and input '?Volume of Type' or '/Volume of Type', press n or N to find previous one next one with string 'Volume of Type'.