grep for path separator - grep

I have some code which has Windows path separator hard-coded all over it.
blah + '\\' + blah
I've been trying to find them with
grep -FR "\\\\" *.py
grep -ER "^(.+?)\\\\" *.py
which are obvious failures. What should the expression be?

grep -FR '\\' *.py
does work in my environment (tested)
The -F indicates fixed string, and only 2 slashes are needed to match 2 slashes in your file.
I hope this helps.

\ is the escape character, so to get a \, you use \\, and to get \\, you use \\\\
foo#bar: ~ > cat test
blah + '\\' + blah
foo#bar: ~ > grep '\\\\' test
blah + '\\' + blah

try
grep '\\\\' *.py
if you want to grab 2 slashes

Related

how to avoid lookbehind assertion is not fixed length

I have a file that contains a version number that I need to output. This version number is apart of a string in this file, that looks something like this:
https://some-link:1234/path/to/file/name-of-file/1.2.345/name-of-file_CXP123456-1.2.345.jar"
I need to get the version number, which is 1.2.345.
This grep command works: grep -Po '(?<=/name-of-file_CXP123456-/)\d.\d.\d\d\d'. However, the CXP number changes and as such I thought I could do something like this: grep -Po '(?<=/name-of-file_*-/)\d.\d.\d\d\d' but that gives the following:
grep: lookbehind assertion is not fixed length
Is there anything I can add to the grep statement to avoid this?
Ultimately, this is part of a stage in Jenkins to get this version number. The sh command looks something like this:
VERSION = sh 'ssh -tt user#ip-address "cat dir/file*.content | grep -Po '(?<=/name-of-file_*-/)\d.\d.\d\d\d' 1>&2"'
You can use
grep -Po '/name-of-file_.*-\K\d+(?:\.\d+)+'
See the regex demo. Details:
/name-of-file_ - a literal text
.* - any zero or more chars other than line break chars as many as possible
- - a hyphen
\K - a match reset operator that omits all text matched so far from the memory buffer
\d+ - one or more digits
(?:\.\d+)+ - one or more sequences of a . and one or more digits.
You don't need lookbehind for this job. You also don't need PCREs, or grep at all.
#!/usr/bin/env bash
# ^^^^- bash, *not* sh
case $BASH_VERSION in '') echo "ERROR: bash required" >&2; exit 1;; esac
string="https://some-link:1234/path/to/file/name-of-file/1.2.345/name-of-file_CXP123456-1.2.345.jar"
regex='.*/name-of-file_CXP[[:digit:]]+-([[:digit:].]+)[.]jar'
if [[ $string =~ $regex ]]; then
echo "Version is ${BASH_REMATCH[1]}"
else
echo "No version found in $string"
fi
Maybe too long for a comment... It looks like the version number is the 2nd-to last field if you split on forward slash?
rev | cut -d/ -f 2 | rev
awk -F/ '{print $(NF-1)}'
perl -lanF/ -e 'print $F[-2]'
Or even something like: basename $(dirname $(cat filename))
For those that are really desperate there is another solution which requires you to pre-build your regex string.
It's not a solution I would recommend but if there is really no other way no one can stop you.
While even with this you won't have true dynamic look-behinds and it is still quite limited it is an option available to you.
The idea is to build the look-behind for each possible length you need it to be.
So for example only match if it's not preceded by a # (0 to a 100 characters look-behind).
reg='';
for ((i = 0 ; i <= 100 ; i++)); do reg+='(?<!#.{'"${i}"'})'; done;
reg+='someVariableName=.*?($|;|\\n)';
grep --perl-regexp "$reg" /usr/local/mgmsbox/msc/scripts/msc.cfg
This might not be the best example but it gets the idea across.
This solution has it's own pitfalls. For example you need to double escape \\ escape-sequences like \n and any character that should not be interpreted should be put in a single-quote string (or use printf).

Regex for line containing one or more spaces or dashes

I got .txt file with city names, each in separate line. Some of them are few words with one or multiple spaces or words connected with '-'. I need to create bash command which will echo those lines out. Currently I'm using cat piped with grep but I can't get both spaces and dash into one search and I had problems with checking for multiple spaces.
print lines with dash:
cat file.txt | grep ".*-.*"
print lines with spaces:
cat file.txt | grep ".*\s.*"
tho when I try to do:
cat file.txt | grep ".*\s+.*"
I get nothing.
Thanks for help
Something like that should work:
grep -E -- ' |\-' file.txt
Explanation:
-E: to interpret patterns as extended regular expressions
--: to signify the end of command options
' |\-': the line contains either a space or a dash
This does not directly address your question, but is too much to put in a comment.
You don't need the .* in your patterns. .* at the beginning or end of a pattern is useless, because it means "0 or more of any character" and so will always match.
These lines are all identical:
cat file.txt | grep ".*-.*"
cat file.txt | grep "-.*"
cat file.txt | grep "-"
Plus you don't need to cat and pipe:
grep "-" file.txt
When grep pattern matches, the default action is to print the whole line, so .* in all your patterns are redundant, you may delete them. Also, you don't have to use cat file | as you may specify the file to grep directly after pattern, i.e. grep 'pattern' file.txt.
Here are some more details:
grep ".*-.*" = grep -- "-" - returns any lines having a - char (-- singals the end of options, the next thing is the pattern)
grep ".*\s.*" = grep "\s" - matches and returns lines containing a whitespace char (only GNU grep)
grep ".*\s+.*" = grep "\s+" - returns line containing a whitespace followed with a literal + char (since you are using POSIX BRE regex here the unescaped + matches a literal plus symbol).
You want
grep "[[:space:]-]" file.txt
See the online demo:
#!/bin/bash
s='abc - def
ghi
jkl mno'
grep '[[:space:]-]' <<< "$s"
Output:
abc - def
jkl mno
The [[:space:]-] POSIX BRE and ERE (enabled with -E option) compliant pattern matches either any whitespace (with the [:space:] POSIX character class) or a hyphen.
Note that [\s-] won't work since \s inside a bracket expression is not treated as a regex escape sequence but as a mere \ or s.

Grep for lines that starts with " followed by 10 digits ",""

e.g.
Find line "1437421130",""
but not "1437421130","92729392"
Cant figure out how to handle double quotes. ( I am an idiot when it comes to grep )
I tried
echo "1437421130","" | grep '"\d{10}",""'
echo "1437421130","" | grep '"[0-9]{10}",""'
Did this on centos. Used single quotes to avoid the double quote escaping. -E to allow the {10}

replace ruby code in all files with unix command

I have a string !Rails.env.dev? || params['render_javascript'].
I want to replace this string with render_javascript. It will be lots of work if I do it one file by one file.
I tried to use unix command as follows, but no luck.
for i in $(find . -name "*.rb")
do
       sed 's/!Rails\.env\.dev\? \|\| params\['render_javascript'\]/render_javascript/g' $i > x
       mv x $i
done
Anyone can offer me some help here?
There are few issues in your code/command. First, you are escaping characters unnecessarily. Second, if we use double quotes to quote sed command it will be better in this case. You can try below command:
for i in $(find . -name "*.rb")
do
sed "s/\!Rails\.env\.dev? || params\['render_javascript'\]/render_javascript/g" $i > x
mv x $i
done
sed (GNU sed) uses Basic Regular expression (BRE) which does not have ?, | metacharacters, so you do not have to escape them. Metacharacters ?, | are added by Extended Regular Expresson (ERE).
And, I have used double quotes " to quote the sed command, because there are single quotes ' in your search regex. And because double quotes was used to quote the sed command, we also have to escape the ! character. We have to escape ! because it is a shell special character and expands to something else, even before sed command is run.
If you want to use Extended regular expression (ERE), then you can use -r option with the sed command. In this case, you have escape ? and | character. For example:
sed -r "s/\!Rails\.env\.dev\? \|\| params\['render_javascript'\]/render_javascript/g" $i > x

how to delete line which contain some specific string in shell

Plz help me to delete line which contain / or ab in linux shell
Example:
ghkl
aaaabd
fdkh/dfd
hjnh
after filter : we got:
ghkl
hinh
Thanks !
Using awk:
awk '!/\/|ab/' file
ghkl
hjnh
Using grep:
grep -v "/\|ab" file
ghkl
hjnh
-v inverts the action to not print line with this pattern
'!/\/|\?/'
' start of awk command
! a not, do do not find this
/ start of regex find whats between / and /
\ escape the next character so its not treated as a command
/ since this is escaped find this /
| or. Find this or this
\ a new escape to prevent ? used as code
? since escaped find ?
/ end of regex
' end of awk command

Resources