Match with regex any string except a string provided - regex

In order to configure apache I am strugelling with one regex. My goal is to match any string, but a provided string. I know this has been asked a couple of times on stackoverflow, however I could not fix it so far.
The regex should match
/home/www/dir1/*
/home/www/dir_wl/example1/*
/home/www/dir_wl/example2/*
It should not match
/home/www/dir1/MEW/*
/home/www/dir_wl/example1/MEW/*
/home/www/dir_wl/example2/MEW*
Here is the entire line:
<Directory ~ "^/home/www/(dir1|dir_wl/.*(?!MEW))/(?!MEW/)">
Any help is greatly apreciated!

I got it with "grep -P". "-P" means "Interpret PATTERN as a Perl regular expression". The program you are working with must support this.
I created the file "dirs.txt" with the following content:
/home/www/dir1/*
/home/www/dir_wl/example1/*
/home/www/dir_wl/example2/*
/home/www/dir1/MEW/*
/home/www/dir_wl/example1/MEW/*
/home/www/dir_wl/example2/MEW*
Then I run this command.
cat dirs.txt | grep -P "^/home/www/(dir1|dir_wl)/(?!MEW)(((?!/MEW).)*$)"
It returns ...
/home/www/dir1/*
/home/www/dir_wl/example1/*
/home/www/dir_wl/example2/*
This does the same on a much more simple way ...
cat regex.txt | grep -E "^/home/www/(dir1|dir_wl)/" | grep -v -E "/MEW"

Related

Can grep show only result i want

I have data as this
tatusx2.atc?beginnum=0;8pctgRB Mwdf fgEio"text1"text4"text
tatqsx3.atc?beginnum=1;8pctgRBwsaNezxio"text2
tatssx4.atc?beginnum=2;8pctgsvMALNejkio"data2
tatksx4.atc?beginnum=1;8pctgxdfALNebfio"text3
tatzsx5.atc?beginnum=3;8pwerRBMALNetior"datac
How to get only data between ; and "
I have tried grep -oP ';.*?"' file and got output :
;8pctgRBMwdffgEio"
;8pctgRBwsaNezxio"
;8pctgsvMALNejkio"
;8pctgxdfALNebfio"
;8pwerRBMALNetior"
But my desired output is:
8pctgRB Mwdf fgEio
8pctgRBwsaNezxio
8pctgsvMALNejkio
8pctgxdfALNebfio
8pwerRBMALNetior
You need to use lookahead and lookbehind regex expressions
grep -oP '(?<=;)\w*(?=")'
I consider you play around regexr to learn more about regular expressions. Checkout their cheatsheet.
A much more readable way to write the expression you need is:
grep -oP '(?<=;).*(?=")' file
and will get you the desired result. PERL regexes are apparently experimental but certain patterns work without issues.
The following options are being used:
-o --only-matching to the print only the matched parts of a matching line
-P --perl-regexp
Using ?=; will get you the string beginning with ; but using the > you are able to start at the index after. Similarly the end string tag is specified.
Here is suggested additional reading.

How can I use sed to regex string and number in bash script

I want to separate string and number in a file to get a specific number in bash script, such as:
Branches executed:75.38% of 1190
I want to only get number
75.38
. I have try like the code below
$new_value=value | sed -r 's/.*_([0-9]*)\..*/\1/g'
but it was incorrect and it was failed.
How should it works? Thank you before for your help.
You can use the following regex to extract the first number in a line:
^[^0-9]*\([0-9.]*\).*$
Usage:
% echo 'Branches executed:75.38% of 1190' | sed 's/^[^0-9]*\([0-9.]*\).*$/\1/'
75.38
Give this a try:
value=$(sed "s/^Branches executed:\([0-9][.0-9]*[0-9]*\)%.*$/\1/" afile)
It is assumed that the line appears only once in afile.
The value is stored in the value variable.
There are several things here that we could improve. One is that you need to escape the parentheses in sed: \(...\)
Another one is that it would be good to have a full specification of the input strings as well as a good script that can help us to play with this.
Anyway, this is my first attempt:
Update: I added a little more bash around this regex so it'll be more easy to play with it:
value='Branches executed:75.38% of 1190'
new_value=`echo $value | sed -e 's/[^0-9]*\([0-9]*\.[0-9]*\).*/\1/g'`
echo $new_value
Update 2: as john pointed out, it will match only numbers that contain a decimal dot. We can fix it with an optional group: \(\.[0-9]\+\)?.
An explanation for the optional group:
\(...\) is a group.
\(...\)? Is a group that appears zero or one times (mind the question mark).
\.[0-9]\+ is the pattern for a dot and one or more digits.
Putting all together:
value='Branches executed:75.38% of 1190'
new_value=`echo $value | sed -e 's/[^0-9]*\([0-9]\+\(\.[0-9]\+\)\?\).*/\1/g'`
echo $new_value

Unix: Cut string by regex delimiter

I have function that prints out the longest path in directory tree. Let's say the function prints this: ./.mozilla/firefox/z6upkljn.default/storage/permanent/chrome/idb/2918063365piupsah.files
What I want to do is to cut this string after match with user defined regex.
For example if user puts in regex like: *de?a*, the only match is z6upkljn.default. So at the end, the output will be ./.mozilla/firefox
Here is a code sample I found sed 's/My_expression.*//'
Where the My_expression is regular expression and delimiter for cutting defined by user.
It works for this input $echo /homes/eva/xm/xmikfi00 | sed 's/mik.*//', where for output I get /homes/eva/xm/x. As expected.
But if I enter simple regex $echo /homes/eva/xm/xmifki00 | sed 's/mi?.*//', the output is /homes/eva/xm/xmikfi00. Anyone who can help me how to get the same output as in the previous example?
I'll be glad for any help or suggestions, thanks.
Sed uses (by default) POSIX BREs, not EREs. If what you're trying to match with your ? is "any character", use a .: echo /homes/eva/xm/xmifki00 | sed 's/mi..*//'.
See man 7 re_format for more details.

search multiple strings in a single line with multiple spaces in between

I want to search for the whole line below from my /etc/pam.d/su file to use it in a script:
auth required pam_wheel.so use_uid
there might be multiple spaces in between, and it might be commented out also, with multiple #'s
This is what I'm using :
grep "^#*auth +required +pam_wheel\.so +use_uid$"
, but it doesn't yield anything
I'm certainly doing something wrong, but what am I doing wrong? Sorry, have always been bad with regular expressions
egrep is the way to go, but the question said "multiple" spaces. That can be done like this
egrep "^([[:space:]]*#)*[[:space:]]*auth[[:space:]]+required[[:space:]]+pam_wheel\.so[[:space:]]+use_uid[[:space:]]*$"
A backslashed space "\ " is not listed in the special escapes in regex(7) Instead, the POSIX character class can be used. You could also use blank (a GNU extension) rather than space to make this only space/tab.
you can use grep -E (extended regexp)
grep -E "^\ +auth\ +required\ +pam_wheel\.so +use_uid$"
this works:
echo " auth required pam_wheel.so use_uid" | grep -E "^\ +auth\ +required\ +pam_wheel\.so +use_uid$"
gives
auth required pam_wheel.so use_uid
Well this finally works for me:
[root#server4 ~]# egrep "^#*auth.*required.*pam_wheel\.so.*use_uid" /etc/pam.d/su
#auth required pam_wheel.so use_uid
I think the issue is in how we are mentioning the spaces.

grep - search for "<?\n" at start of a file

I have a hunch that I should probably be using ack or egrep instead, but what should I use to basically look for
<?
at the start of a file? I'm trying to find all files that contain the php short open tag since I migrated a bunch of legacy scripts to a relatively new server with the latest php 5.
I know the regex would probably be '/^<\?\n/'
I RTFM and ended up using:
grep -RlIP '^<\?\n' *
the P argument enabled full perl compatible regexes.
If you're looking for all php short tags, use a negative lookahead
/<\?(?!php)/
will match <? but will not match <?php
[meder ~/project]$ grep -rP '<\?(?!php)' .
find . -name "*.php" | xargs grep -nHo "<?[^p^x]"
^x to exclude xml start tag
if you worried about windows line endings, just add \r?.
grep '^<?$' filename
Don't know if that is showing up correctly. Should be
grep ' ^ < ? $ ' filename
Do you mean a literal "backslash n" or do you mean a newline?
For the former:
grep '^<?\\n' [files]
For the latter:
grep '^<?$' [files]
Note that grep will search all lines, so if you want to find matches just at the beginning of the file, you'll need to either filter each file down to its first line, or ask grep to print out line numbers and then only look for line-1 matches.