How would I use grep on a single word in UNIX? - bash

I want to run a script in unix that will look for a specific pattern inside a passed argument. The argument is a single word, in all cases. I cannot use grep, as grep only works on searching through files. Is there a better unix command out there that can help me?

Grep can search though files, or it can work on stdin:
$ echo "this is a test" | grep is
this is a test

Depending on what you're doing you may prefer to use bash pattern matching:
# Look for text in $word
if [[ $word == *text* ]]
then
echo "Match";
fi
or regular expressions:
# Check is $regex matches $word
if [[ $word =~ $regex ]]
then
echo "Match";
fi

you can use case/esac as well. No need to call any external commands (for your case)
case "$argument" in
*text* ) echo "found";;
esac

As of bash 3.0 it has a built in regexp operator =~
Checkout http://aplawrence.com/Linux/bash-regex.html

if echo $argument | grep -q pattern
then
echo "Matched"
fi

my File is:
$ cat > log
loga
hai how are you loga
hai
hello
loga
My command is:
sed -n '/loga/p' log
My answer is:
loga
hai how are you loga
loga

Related

Grep only string in a line in shell script

I writing a shell script.
The line will look like:
"holderIdentity":"leader-elector1-5cd5b9d76d-ztfgf","numberofLeader":{"":0,"node2":1,"node3":2,"node4":2}"
The character 5cd5b9d76d-ztfgf will be created randomly, so my keyword to grep is just only leader-elector. And the string ,"numberofLeader":{"":0,"node2":1,"node3":2,"node4":2}" is also randomly (it is diffent everytime)
How can I get just this string leader-elector1-5cd5b9d76d-ztfgf from the line.
Thank you so much!
using GNU grep
grep -Eo 'leader-elector[^"]*' <<< '"holderIdentity":"leader-elector1-5cd5b9d76d-ztfgf","numberofLeader":{"":0,"node2 ":1,"node3":2,"node4":2}"'
otherwise with bash regex feature
var='"holderIdentity":"leader-elector1-5cd5b9d76d-ztfgf","numberofLeader":{"":0,"node2 ":1,"node3":2,"node4":2}"'
re='leader-elector[^"]*'
if [[ $var =~ $re ]] ; then
declare -p BASH_REMATCH
echo "${BASH_REMATCH[0]}"
fi

failing bash variable matching

I have been driving myself mad on this.
I just don't see why it doesn't work when bash variables are untyped.
There should be no reason why not.
pat1=`. $NVM_DIR/nvm.sh && nvm ls | sed 's/\x1b\[[^\x1b]*m//g' | sed -e 's/[[:alpha:]|\/\)\-\>\(|[:space:]]//g' | sed 's/[-|\*]//g' | sed '/^$/d'`
pat2=`. $NVM_DIR/nvm.sh && nvm ls node | head -1 | awk '{print $2}' | cut -d v -f2`
these expand to:
~$ echo $pat1
9.5.0
9.5.0
9.5
9.5.0
4.8.7
6.12.3
8.9.4
~$ echo $pat2
9.5.0
So I want to check if the string found in $pat2 is in $pat1 string.
however it does not find it even though it clearly is in the pattern 3 times at least.
Checking for the pattern with a test like:
case "$pat1" in
*$pat2*)
echo 'match'
;;
*)
echo 'nomatch'
;;
esac
this gives:
~$ ./test.sh
nomatch
another test:
if [[ "$pat1" =~ "$pat2" ]]; then
echo 'match'
else
echo 'nomatch'
fi
again fails:
~$ ./test.sh
nomatch
Even tried some janky hacky method to no avail,
echo $pat1 | grep "$pat2" > /dev/null
if [ $? -eq 0 ]; then
echo "matched"
else
echo "nomatch"
fi
gives the result:
~$ ./test.sh
grep: brackets ([ ]) not balanced
nomatch
Been pulling my hair out today working on this.
This must be due to the fact that both variables are command substitutions, it leads me to believe it is comparing the actual commands themselves rather than their output stored in the variables.
So even though they echo the output, i think it may be comparing the string of the commands itself.
am I wrong? can anyone explain why this fails to match and if its possible with bash to compare the output of two commands in a string/sub-string type of comparison?
I put your pat1 and pat2 values in files and didn't need to use | anywhere.
#!/bin/bash
pat1=$(cat pat1|tr '\012' ' ')
pat2=$(<pat2)
#tst pat2="10.1"
echo "$pat1"
case "$pat1" in
*$pat2*)
echo 'match'
;;
*)
echo 'nomatch'
;;
esac
Produces
#dbg:pat2=9.5.0 pat1=9.5.0 9.5.0 9.5 9.5.0 4.8.7 6.12.3 8.9.4
match
If I un-comment the #tst pat2 line, the output is
#dbg:pat2=10.1 pat1=9.5.0 9.5.0 9.5 9.5.0 4.8.7 6.12.3 8.9.4
nomatch
Is there any chance your data was created for MS Windows? If so, check for Windows line endings with
head -10 file | cat -vet
if you see ^M$ at the end of each line, then run dos2unix file .... (multiple file can be processed in one invocation, and the original file is overwritten with the same name.
IHTH
nomatch
The grep version is almost right, but you need to quote $pat1, otherwise the newlines will be converted to spaces and everything will be on one line.
if echo "$pat1" | grep -F -q "$pat2"
then
echo "matched"
else
echo "nomatch"
fi
I've also added the -F option to grep so it will treat $pat2 as a fixed string rather than a regular expression.
DEMO

Bash: Replace part of string with wildcard in search pattern

I have working script that looks for errors in log files :
CONFIGFILE=testfmc.ini
log=log1.log
res=0
while read line ;
do
echo "$line"
if [[ "$line" == PAT[0-9][0-9]* ]] ; then
echo "line --$line--"
patnum=$(echo "$line" | awk -F= '{print $1}');
pattern=$(echo "$line" | awk -F= '{print $2}');
echo "$patnum --- $pattern";
res=$(fgrep -c "$pattern" $log );
if [[ "$res" -gt 0 ]] ; then
echo "Error in log files $res";
fi
echo "End of IF";
fi
echo $res;
done < $CONFIGFILE
testfmc.ini is the file with the patterns :
PAT01=java.net.SocketException: Connection reset
PAT02=javax.mail.StoreClosedException: failed to create new store connection
PAT03=javax.mail.MessagingException: ServerName NO Server Unavailable
PAT04=javax.mail.FolderClosedException: * BYE Connection is closed
The problem is that in PAT03 there is a Server name and this error may show up with several Server names. How can i replace the ServerName in the pattern with WILDCARD. I have tried with * or * or "*" and several more options , but nothing works.
The desired operation (replacing part of a string with a wildcard) is trivially done with a parameter expansion:
s='PAT03=javax.mail.MessagingException: ServerName NO Server Unavailable'
s2="${s//ServerName/'*'}"
echo "$s2"
(There are other issues with your script as a whole -- fgrep matches literal strings, not regular expressions or glob-style patterns, and the other grep variants use regexes while your patterns here are glob-style -- but if your intended question's scope expands beyond what's in the title, you should be asking a new question directly on point rather than slipping what you actually want to know into the details of a different question entirely).
in ini file replace:
PAT03=javax.mail.MessagingException: ServerName NO Server Unavailable
with
PAT03=javax.mail.MessagingException: .* NO Server Unavailable
in script replace:
res=$(fgrep -c "$pattern" $log );
with:
res=$(grep -E "$pattern" $log );
the script is not well optimized but works so :) good luck
I don't think you can use fgrep to do that. I thought fgrep only looks for strings, not patterns.
Perhaps use normal grep or egrep, and put the pattern as .* rather than *.
PS #Charles suggestion regarding IFS is great.

String manipulation Bash-Extensions

In my script I'm trying to take a string, then output the extension of a string if it has one. So essentially I take the basename of a file, then output anything that comes after a period.
What's the syntax to do something like this?
For example
dotcutter.sh
file=testfile.jpg
the script should output .jpg
EDIT:
I've solved my problem now with:
file=$(basename "$1" )
stub=${file%.*}
echo ${file#"$stub"}
Which reduces my argument to a basename, thank you all.
$ file=testfile.jpg
$ echo ${file##*.}
jpg
$ file=testfile.ext1.ext2
$ echo ${file##*.}
ext2
$ file=noextension
$ echo ${file##*.}
noextension
Notice that it doesn't work if the file has no extension. If that's important then try this two-step solution:
$ file=testfile.ext1.ext2
$ stub=${file%.*}
$ echo ${file#"$stub"}
.ext2
Or this regex-based one, which will only call echo if there's actually an extension. (&& is shorthand for "if then".)
$ regex='(\.[^.]*)$'
$ file=testfile.ext1.ext2
$ [[ $file =~ $regex ]] && echo ${BASH_REMATCH[1]}
.ext2
$ file=noextension
$ [[ $file =~ $regex ]] && echo ${BASH_REMATCH[1]}
See also:
basename(1)
dirname(1)
Bash FAQ: How can I use parameter expansion? How can I get substrings? How can I get a file without its extension, or get just a file's extension?]
Try the following code :
file=testfile.jpg
echo .${file#*.}
That use parameter expansion

bash search for string in each line of file

I'm trying what seems like a very simple task: use bash to search a file for strings, and if they exist, output those to another file. It could be jetlag, but this should work:
#!/bin/bash
cnty=CNTRY
for line in $(cat wheatvrice.csv); do
if [[ $line = *$cnty* ]]
then
echo $line >> wr_imp.csv
fi
done
I also tried this for completeness:
#!/bin/bash
cnty=CNTRY
for line in $(cat wheatvrice.csv); do
case $line in
*"$cnty"*) echo $line >> wr_imp.csv;;
*) echo "no";;
esac
done
both output everything, regardless of whether the line contains CNTRY or not, and I'm copy/pasting from seemingly reliable sources, so apparently there's something simple about bash-ness that I'm missing?
Don't use bash, use grep.
grep -F "$cnty" wheatvrice.csv >> wr_imp.csv
While I would suggest to simply use grep too, the question is open, why you approach didn't work. Here a self referential modification of your second approach - with keyword 'bash' to match itself:
#!/bin/bash
cnty=bash
while read -r line
do
case $line in
*${cnty}*)
echo $line " yes" >> bashgrep.log
;;
*)
echo "no"
;;
esac
done < bashgrep.sh
The keypoint is while read -r line ... < FILE. Your command with cat involves String splitting, so every single word is processed in the loop, not every line.
The same problem in example 1.

Resources