bash: grep wildcard start and end with - linux

i have a bash script like this:
TABLE_TO_IGNORE=$(mysql -u $DBUSER -p$DBPASS -h $DBHOST -N <<< "show tables from $DBNAME" | grep "^$i" | xargs);
currently i only able to grep the text starting with. How to write the code that to determine the text ending with?
let say 1:
my $i is:
test1_*
tb2_*
tb3_*
with the * at the back part, it will grep as text starting with those value
let say 2:
my $i is:
*_sometext1
*sometext2
with the * at the front, it will grep as text ending with those value.
i know this:
grep '^sometext1' files = 'sometext1' at the start of a line
grep 'sometext2$' files = 'sometext2' at the end of a line
question is: how do i write the if else to my bash code identify the * is in front or back?
Note: You can ignore my bash code, i just need the if else condition to determine the "*" is in front or at the back of the string.
Any help would be great.
Thanks

You can try this code.
#!/bin/bash
stringToTest="Hello World!*"
echo $stringToTest | grep "^\*.*" > /dev/null
if [ $? -eq 0 ]; then
echo "Asterisk is at the front"
fi
echo $stringToTest | grep "^.*\*$" > /dev/null
if [ $? -eq 0 ]; then
echo "Asterisk is at the back"
fi
As shown in this code, I made use of exit code ($?) to determine whether the regular expression matches the string. As shown in man grep:
Normally, exit status is 0 if selected lines are found and 1
otherwise.
Hope this helps.

Related

LINUX script bash [duplicate]

I want to check if a file contains a specific string or not in bash. I used this script, but it doesn't work:
if [[ 'grep 'SomeString' $File' ]];then
# Some Actions
fi
What's wrong in my code?
if grep -q SomeString "$File"; then
Some Actions # SomeString was found
fi
You don't need [[ ]] here. Just run the command directly. Add -q option when you don't need the string displayed when it was found.
The grep command returns 0 or 1 in the exit code depending on
the result of search. 0 if something was found; 1 otherwise.
$ echo hello | grep hi ; echo $?
1
$ echo hello | grep he ; echo $?
hello
0
$ echo hello | grep -q he ; echo $?
0
You can specify commands as an condition of if. If the command returns 0 in its exitcode that means that the condition is true; otherwise false.
$ if /bin/true; then echo that is true; fi
that is true
$ if /bin/false; then echo that is true; fi
$
As you can see you run here the programs directly. No additional [] or [[]].
In case if you want to check whether file does not contain a specific string, you can do it as follows.
if ! grep -q SomeString "$File"; then
Some Actions # SomeString was not found
fi
In addition to other answers, which told you how to do what you wanted, I try to explain what was wrong (which is what you wanted.
In Bash, if is to be followed with a command. If the exit code of this command is equal to 0, then the then part is executed, else the else part if any is executed.
You can do that with any command as explained in other answers: if /bin/true; then ...; fi
[[ is an internal bash command dedicated to some tests, like file existence, variable comparisons. Similarly [ is an external command (it is located typically in /usr/bin/[) that performs roughly the same tests but needs ] as a final argument, which is why ] must be padded with a space on the left, which is not the case with ]].
Here you needn't [[ nor [.
Another thing is the way you quote things. In bash, there is only one case where pairs of quotes do nest, it is "$(command "argument")". But in 'grep 'SomeString' $File' you have only one word, because 'grep ' is a quoted unit, which is concatenated with SomeString and then again concatenated with ' $File'. The variable $File is not even replaced with its value because of the use of single quotes. The proper way to do that is grep 'SomeString' "$File".
Shortest (correct) version:
grep -q "something" file; [ $? -eq 0 ] && echo "yes" || echo "no"
can be also written as
grep -q "something" file; test $? -eq 0 && echo "yes" || echo "no"
but you dont need to explicitly test it in this case, so the same with:
grep -q "something" file && echo "yes" || echo "no"
##To check for a particular string in a file
cd PATH_TO_YOUR_DIRECTORY #Changing directory to your working directory
File=YOUR_FILENAME
if grep -q STRING_YOU_ARE_CHECKING_FOR "$File"; ##note the space after the string you are searching for
then
echo "Hooray!!It's available"
else
echo "Oops!!Not available"
fi
grep -q [PATTERN] [FILE] && echo $?
The exit status is 0 (true) if the pattern was found; otherwise blankstring.
if grep -q [string] [filename]
then
[whatever action]
fi
Example
if grep -q 'my cat is in a tree' /tmp/cat.txt
then
mkdir cat
fi
In case you want to checkif the string matches the whole line and if it is a fixed string, You can do it this way
grep -Fxq [String] [filePath]
example
searchString="Hello World"
file="./test.log"
if grep -Fxq "$searchString" $file
then
echo "String found in $file"
else
echo "String not found in $file"
fi
From the man file:
-F, --fixed-strings
Interpret PATTERN as a list of fixed strings, separated by newlines, any of
which is to be matched.
(-F is specified by POSIX.)
-x, --line-regexp
Select only those matches that exactly match the whole line. (-x is specified by
POSIX.)
-q, --quiet, --silent
Quiet; do not write anything to standard output. Exit immediately with zero
status if any match is
found, even if an error was detected. Also see the -s or --no-messages
option. (-q is specified by
POSIX.)
Try this:
if [[ $(grep "SomeString" $File) ]] ; then
echo "Found"
else
echo "Not Found"
fi
I done this, seems to work fine
if grep $SearchTerm $FileToSearch; then
echo "$SearchTerm found OK"
else
echo "$SearchTerm not found"
fi
grep -q "something" file
[[ !? -eq 0 ]] && echo "yes" || echo "no"

How would I split a word from number in bash and create a variable from it?

I have a word FOO123USR I would like to split the foo and have it in its own variable and also the 123 in its own variable and finally I would like to get rid of the USR. I'm having trouble trying to accomplish this.
This is how my script looks so far but I am getting a blank output
#!/bin/bash
#var holding
RED='\033[0;31m'
NC='\033[0m'
var2=$(echo $START_VAR | grep -o -E '[0-9]+')
var1=${START_VAR//[A-Z]/}
if [ "$EUID" -ne 0 ];
then
echo -e "${RED} YOU MUST RUN AS ROOT USER ! ${NC}\n"
exit
fi
# We are getting the username here
read -p "Type the username <example: FOO123USR> [ENTER]: " START_VAR
echo "$va2"
echo "$var1"
One way to do this type of tinkering:
START_VAR=FOO123USR
var1=${START_VAR%%[0-9]*} # remove from first number to end
var2=${START_VAR//[A-Z]/} # remove ALL uppercase letters
More examples and info: https://www.gnu.org/software/bash/manual/html_node/Shell-Parameter-Expansion.html
:)
Dale

How can I obtain command returning status in linux shell

Say, I call grep "blabla" $file in my shell. How could I know whether grep found "blabla" in $file?
I try ret='grep "blabla" $file', will this work by viewing the value of ret? If yes, is ret integer value or string value or something else?
If you do exactly
ret='grep "blabla" $file'
then ret will contain the string "grep "blabla" $file".
If you do (what you meant)
ret=`grep "blabla" $file`
then ret will contain whatever output grep spit out (the lines that matched "blabla" in $file).
If you just want to know whether grep found any lines that matched "blabla" in $file then you want to check the return code of grep -q blabla "$file" (note that you don't need to quote literal strings when they don't contain special characters and that you should quote variable references).
The variable $? contains the return code of the most recently executed command. So
grep -q blabla "$file"
echo "grep returned: $?"
will echo the return code from grep which will be 0 if any lines were output.
The simplest way to test that and do something about it is, however, not to use $? at all but instead to just embed the grep call in an if statement like this
if grep -q blabla "$file"; then
echo grep found something
else
echo grep found nothing
fi
When you run the command
grep blabla "$file"
Status is saved in the variable $?. 0 is good, greater than 0 is bad. So you
could do
grep -q blabla "$file"
if [ $? = 0 ]
then
echo found
fi
Or save to a variable
grep -q blabla "$file"
ret=$?
if [ $ret = 0 ]
then
echo found
fi
Or just use if with grep directly
if grep -q blabla "$file"
then
echo found
fi

How to add line number for output, prompt for line, then act based on input?

I wrote a shell script like this:
#! /bin/sh
...
ls | grep "android"
...
and the output is :
android1
android2
xx_android
...
I want to add a number in each file, like this:
1 android1
2 android2
3 XX_android
...
please choose your dir number:
and then wait for the user input line number x, the script reads the line number back then process the corresponding dir. How can we do this in shell ? Thanks !
nl prints line numbers:
ls | grep android | nl
If you pipe the result into cat, you can use the -n option to number each line like so:
ls | grep "android" | cat -n
Pass -n to grep, as follows:
ls | grep -n "android"
From the grep man-page:
-n, --line-number
Prefix each line of output with the line number within its input file.
Instead of implementing the interaction, you can use built-in command select.
select d in $(find . -type d -name '*android*'); do
if [ -n "$d" ]; then
# put your command here
echo "$d selected"
fi
done
The other answers on this page actually don't answer the question 100%. They don't show how to let the user interactively choose the file from another script.
The following approach will allow you to do this, as can be seen in the example. Note that the select_from_list script was pulled from this stackoverflow post
$ ls
android1 android4 android7 mac2 mac5
android2 android5 demo.sh mac3 mac6
android3 android6 mac1 mac4 mac7
$ ./demo.sh
1) android1 3) android3 5) android5 7) android7
2) android2 4) android4 6) android6 8) Quit
Please select an item: 3
Contents of file selected by user: 2.3 Android 1.5 Cupcake (API 3)
Here's the demo.sh and the script it uses to select an item from a list, select_from_list.sh
demo.sh
#!/usr/bin/env bash
# Ask the user to pick a file, and
# cat the file contents if they select a file.
OUTPUT=$(\ls | grep android | select_from_list.sh | xargs cat)
STATUS=$?
# Check if user selected something
if [ $STATUS == 0 ]
then
echo "Contents of file selected by user: $OUTPUT"
else
echo "Cancelled!"
fi
select_from_list.sh
#!/usr/bin/env bash
prompt="Please select an item:"
options=()
if [ -z "$1" ]
then
# Get options from PIPE
input=$(cat /dev/stdin)
while read -r line; do
options+=("$line")
done <<< "$input"
else
# Get options from command line
for var in "$#"
do
options+=("$var")
done
fi
# Close stdin
0<&-
# open /dev/tty as stdin
exec 0</dev/tty
PS3="$prompt "
select opt in "${options[#]}" "Quit" ; do
if (( REPLY == 1 + ${#options[#]} )) ; then
exit 1
elif (( REPLY > 0 && REPLY <= ${#options[#]} )) ; then
break
else
echo "Invalid option. Try another one."
fi
done
echo $opt
This works for me:
line-number=$(ls | grep -n "android" | cut -d: -f 1)
I use this in a script to remove sections of my sitemap.xml which I don't want Googlebot to crawl. I search for the URL (which is unique) and then find the line number using the above. Using simple maths the script then calculates the range of numbers required to delete the entire entry in the XML file.
I agree with jweyrich regarding updating your question to get better answers.

How to test if string exists in file with Bash?

I have a file that contains directory names:
my_list.txt :
/tmp
/var/tmp
I'd like to check in Bash before I'll add a directory name if that name already exists in the file.
grep -Fxq "$FILENAME" my_list.txt
The exit status is 0 (true) if the name was found, 1 (false) if not, so:
if grep -Fxq "$FILENAME" my_list.txt
then
# code if found
else
# code if not found
fi
Explanation
Here are the relevant sections of the man page for grep:
grep [options] PATTERN [FILE...]
-F, --fixed-strings
        Interpret PATTERN as a list of fixed strings, separated by newlines, any of which is to be matched.
-x, --line-regexp
        Select only those matches that exactly match the whole line.
-q, --quiet, --silent
        Quiet; do not write anything to standard output. Exit immediately with zero status if any match is found, even if an error was detected. Also see the -s or --no-messages option.
Error handling
As rightfully pointed out in the comments, the above approach silently treats error cases as if the string was found. If you want to handle errors in a different way, you'll have to omit the -q option, and detect errors based on the exit status:
Normally, the exit status is 0 if selected lines are found and 1 otherwise. But the exit status is 2 if an error occurred, unless the -q or --quiet or --silent option is used and a selected line is found. Note, however, that POSIX only mandates, for programs such as grep, cmp, and diff, that the exit status in case of error be greater than 1; it is therefore advisable, for the sake of portability, to use logic that tests for this general condition instead of strict equality with 2.
To suppress the normal output from grep, you can redirect it to /dev/null. Note that standard error remains undirected, so any error messages that grep might print will end up on the console as you'd probably want.
To handle the three cases, we can use a case statement:
case `grep -Fx "$FILENAME" "$LIST" >/dev/null; echo $?` in
0)
# code if found
;;
1)
# code if not found
;;
*)
# code if an error occurred
;;
esac
Regarding the following solution:
grep -Fxq "$FILENAME" my_list.txt
In case you are wondering (as I did) what -Fxq means in plain English:
F: Affects how PATTERN is interpreted (fixed string instead of a regex)
x: Match whole line
q: Shhhhh... minimal printing
From the man file:
-F, --fixed-strings
Interpret PATTERN as a list of fixed strings, separated by newlines, any of which is to be matched.
(-F is specified by POSIX.)
-x, --line-regexp
Select only those matches that exactly match the whole line. (-x is specified by POSIX.)
-q, --quiet, --silent
Quiet; do not write anything to standard output. Exit immediately with zero status if any match is
found, even if an error was detected. Also see the -s or --no-messages option. (-q is specified by
POSIX.)
Three methods in my mind:
1) Short test for a name in a path (I'm not sure this might be your case)
ls -a "path" | grep "name"
2) Short test for a string in a file
grep -R "string" "filepath"
3) Longer bash script using regex:
#!/bin/bash
declare file="content.txt"
declare regex="\s+string\s+"
declare file_content=$( cat "${file}" )
if [[ " $file_content " =~ $regex ]] # please note the space before and after the file content
then
echo "found"
else
echo "not found"
fi
exit
This should be quicker if you have to test multiple string on a file content using a loop for example changing the regex at any cicle.
Easiest and simplest way would be:
isInFile=$(cat file.txt | grep -c "string")
if [ $isInFile -eq 0 ]; then
#string not contained in file
else
#string is in file at least once
fi
grep -c will return the count of how many times the string occurs in the file.
Simpler way:
if grep "$filename" my_list.txt > /dev/null
then
... found
else
... not found
fi
Tip: send to /dev/null if you want command's exit status, but not outputs.
Here's a fast way to search and evaluate a string or partial string:
if grep -R "my-search-string" /my/file.ext
then
# string exists
else
# string not found
fi
You can also test first, if the command returns any results by running only:
grep -R "my-search-string" /my/file.ext
grep -E "(string)" /path/to/file || echo "no match found"
-E option makes grep use regular expressions
If I understood your question correctly, this should do what you need.
you can specifiy the directory you would like to add through $check variable
if the directory is already in the list, the output is "dir already listed"
if the directory is not yet in the list, it is appended to my_list.txt
In one line: check="/tmp/newdirectory"; [[ -n $(grep "^$check\$" my_list.txt) ]] && echo "dir already listed" || echo "$check" >> my_list.txt
The #Thomas's solution didn't work for me for some reason but I had longer string with special characters and whitespaces so I just changed the parameters like this:
if grep -Fxq 'string you want to find' "/path/to/file"; then
echo "Found"
else
echo "Not found"
fi
Hope it helps someone
If you just want to check the existence of one line, you do not need to create a file. E.g.,
if grep -xq "LINE_TO_BE_MATCHED" FILE_TO_LOOK_IN ; then
# code for if it exists
else
# code for if it does not exist
fi
My version using fgrep
FOUND=`fgrep -c "FOUND" $VALIDATION_FILE`
if [ $FOUND -eq 0 ]; then
echo "Not able to find"
else
echo "able to find"
fi
I was looking for a way to do this in the terminal and filter lines in the normal "grep behaviour". Have your strings in a file strings.txt:
string1
string2
...
Then you can build a regular expression like (string1|string2|...) and use it for filtering:
cmd1 | grep -P "($(cat strings.txt | tr '\n' '|' | head -c -1))" | cmd2
Edit: Above only works if you don't use any regex characters, if escaping is required, it could be done like:
cat strings.txt | python3 -c "import re, sys; [sys.stdout.write(re.escape(line[:-1]) + '\n') for line in sys.stdin]" | ...
A grep-less solution, works for me:
MY_LIST=$( cat /path/to/my_list.txt )
if [[ "${MY_LIST}" == *"${NEW_DIRECTORY_NAME}"* ]]; then
echo "It's there!"
else
echo "its not there"
fi
based on:
https://stackoverflow.com/a/229606/3306354
grep -Fxq "String to be found" | ls -a
grep will helps you to check content
ls will list all the Files
Slightly similar to other answers but does not fork cat and entries can contain spaces
contains() {
[[ " ${list[#]} " =~ " ${1} " ]] && echo 'contains' || echo 'does not contain'
}
IFS=$'\r\n' list=($(<my_list.txt))
so, for a my_list.txt like
/tmp
/var/tmp
/Users/usr/dir with spaces
these tests
contains '/tmp'
contains '/bin'
contains '/var/tmp'
contains '/Users/usr/dir with spaces'
contains 'dir with spaces'
return
exists
does not exist
exists
exists
does not exist
if grep -q "$Filename$" my_list.txt
then
echo "exist"
else
echo "not exist"
fi

Resources