I am trying to learn RegEx, but it is hard.
For example, i have 3 files:
$ ls
thisisnothing12.txt Thisisnothing12.txt thisisnothing.txt
I want to use ls to grep out only the 2 files with digits on it..
These are what i have tried, but they doesn't show even a single file.. why ? What's wrong with em ?
$ ls | grep "^[\w]+[\d]+\.[\w]{3}$"
$ ls | grep "^[a-zA-Z]+[0-9]+\.[a-zA-Z]{3}$"
Thx.
There are different regex flavors, see https://stackoverflow.com/a/66256100/7475450
You need to use PCRE if you want to use \d:
$ touch thisisnothing12.txt Thisisnothing12.txt thisisnothing.txt
$ ls
Thisisnothing12.txt thisisnothing.txt thisisnothing12.txt
$ ls | grep '\d' # '\d' does not work in POSIX Basic regex
$ ls | grep -P '\d' # use PCRE regex
Thisisnothing12.txt
thisisnothing12.txt
$
As you can see you can search for just the characters you are interested in.
You can narrow down, such as finding files that start with a number:
$ touch 2feet.txt
$ ls | grep -P '\d'
2feet.txt
Thisisnothing12.txt
thisisnothing12.txt
$ ls | grep -P '^\d'
2feet.txt
$
Learn more with this tutorial: https://twiki.org/cgi-bin/view/Codev/TWikiPresentation2018x10x14Regex
^[\w]+[\d]+\.[\w]{3}$
^[a-zA-Z]+[0-9]+\.[a-zA-Z]{3}$
Let's simplify a bit. They are both essentially the same thing, because [\w] is the same as \w which is [A-Za-z]. And the same for \d.
So we can simplify to
^\w+\d+\.\w{3}$
The issue is that ^ asserts the start of the string, and $ is the end. grep works on each line. And ls returns all results on one line. You can use ls -1 to get one file per line. You also need the -P flag for grep to work with \w and \d.
$ ls -1 | grep -P "^\w+\d+\.\w{3}$"
You can try different regexes here: https://regexr.com/5mujo
Related
I want the output of the sed file edit to go into my log file name d_selinuxlog.txt. Currently, grep outputs the specified string as well as 3 other strings above and below in the edited file.
#!/bin/bash
{ getenforce;
sed -i s/SELINUX=enforcing/SELINUX=disabled /etc/selinux/config;
grep "SELINUX=*" /etc/selinux/config > /home/neb/scropts/logs/d_selinuxlog.txt;
setenforce 0;
getenforce; }
I want to be seeing just SELINUX=disabled in the log file
All the lines with the lines SELINUX are going to match, even the commented ones, so, you need to omit that ones, and the * from the match.
grep "SELINUX=" /etc/selinux/config | grep -v "#"
This is my output
17:52:07 alvaro#lykan /home/alvaro
$ grep "SELINUX=" /etc/selinux/config | grep -v "#"
SELINUX=disabled
17:52:22 alvaro#lykan /home/alvaro
If I use a grep command like this ls | grep '^[-[:alnum:]\._]+$' to match filenames, it outputs no result but when the command changes to ls | grep '^[-[:alnum:]\._]*$', it works correctly. What's going on?
grep uses "basic" regexes by default, where + is a normal character. You need \+ to match 1 or more things (or use grep -E).
I often have to look for specific strings in a big set of log files with grep. And I get lots of results, on what I must scroll a lot.
Today, the results of grep list the results in alphabetical order. I would like to have my grep results reversed ordered by time, like a ls -ltr would do.
I know I could take the result of ls -ltr and grep file by file. I do it like this:
ls -ltr ${my_log_dir}\* | awk '{print $9}' |xargs grep ${my_pattern}
But I wonder: Is there a simpler way?
PS: I'm using ksh on AIX.
The solution I found (thanks to Fedorqui) was to simply use ls -tr. It assumes the results are passed in the right order through the | to xargs allowing then to do the grep.
My misconception was that since when I us ls, the results arrive not as a single column list but as a multiple column list, it couldn't work as an input for xargs.
Here is the simplest solution to date, since it avoids any awk parsing:
ls -tr ${my_log_dir}\* | xargs grep ${my_pattern}
I checked, and every result of the ls -t are passed to xargs even though they look not as I expected they would enter easily in it:
srv:/papi/tata $ ls -t
addl ieet rrri
ooij lllr sss
srv:/papi/tata $ ls -t |xargs -I{} echo {}
addl
ieet
rrri
ooij
lllr
sss
This will work too use find command:-
find -type f -print0 | xargs -r0 stat -c %y\ %n | sort -r | awk '{print $4}' | sed "s|^\./||"
-print0 in find to preserve files having special characters(whitespaces, tabs)
Print file status (stat with %y (Time of last modification) and %n (%n File name) with output having new-separated (-c)
Reverse sort the output from previous command. (-r for reverse)
awk '{print $4}' printing only the file-name (can be optimized as needed)
Removing the leading ./ from the file-names.
I would like to grep digits inside a set of parentheses after a match.
Given foo.txt below,
foo: "32.1" bar: "42.0" misc: "52.3"
I want to extract the number after bar, 42.0.
The following line will match, but I'd like to extract the digit. I guess I could pipe the output back into grep looking for \d+.\d+, but is there a better way?
grep -o -P 'bar: "\d+.\d+"' foo.txt
One way is to use look ahead and look-behind assertions:
grep -o -P '(?<=bar: ")\d+.\d+(?=")'
Another is to use sed:
sed -e 's/.*bar: "\([[:digit:]]\+.[[:digit:]]\+\)".*/\1/'
You could use the below grep also,
$ echo 'foo: "32.1" bar: "42.0" misc: "52.3"' | grep -oP 'bar:\s+"\K[^"]*(?=")'
42.0
I use grep -L to get a list of files that do not contain a certain string. How can I see the content of those files? Just like:
grep -L "pattern" | cat
You can use xargs:
grep -L "pattern" | xargs cat
As read in man xargs --> build and execute command lines from standard input. So it will cat to those file names that grep -L returns.
You can use cat and use the output of grep -L...
cat $(grep -L "pattern" *.files )