I need some help in my shell script. I have this:
#!/bin/bash
for i in $*
do
if [[ $i = *[a-zA-Z] ]]
then echo $i contains just letters.
elif [[ $i = *[a-zA-Z0-9] ]]
then echo $i contains numbers and letters.
else
echo Error.
done
I would like the result to be, for example:
$ ./script.sh abCd a9d a-b
abCd contains just letters.
a9d contains numbers and letters.
Error.
But I get contains just letters in every case.
I also tried grep command too, but without success.
Your RegEx are wrong. Try the following:
#!/bin/bash
for i in $*
do
if [[ $i =~ ^[a-zA-Z]+$ ]]
then echo $i contains just letters.
elif [[ $i =~ ^[a-zA-Z0-9]+$ ]]
then echo $i contains numbers and letters.
else
echo Error.
fi
done
Related
I am novice to linux scripting. For the below example, i need to split the string as per "-" and store the output in an array as a separate element.
Later, i need to validate each element in an array if its an integer or alphanumeric. if its integer, i need to ignore that element and print only non-integer elements. The following script which i am trying is not giving expected output which should be like 'grub2-systemd-sleep-plugin'.
item = grub2-systemd-sleep-plugin-2.02-153.1
IFS='-'
read -rasplitIFS<<< "$item"
for word in "${splitIFS[#]}"; do echo $word; done
Taking a stab at this here...
Depends on how your numbers may be defined, but I believe you could use something like this to removing numbers from the output. I'm not sure if there is a more efficient way to achieve this
for word in ${splitIFS[#]}
do
c=$(echo $word | grep -c -E "^[0-9]+\.{0,}[0-9]+$")
[ $c -eq 0 ] && echo $word
done
If you're using bash, it will be faster if you use built-in tools rather than subshells.
line=grub2-systemd-sleep-plugin-2.02-153.1-foo-1
while [[ -n "$line" ]]
do if [[ "$line" =~ ^[0-9.]+- ]]
then line="${line#*-}"
elif [[ "$line" =~ ^[0-9.]+$ ]]
then break
elif [[ "$line" =~ ^([[:alnum:]]+)- ]]
then echo "${BASH_REMATCH[1]}";
line="${line#*-}"
elif [[ "$line" =~ ^([[:alnum:]]+)$ ]]
then echo "${BASH_REMATCH[1]}";
break
else echo "How did I get here?"
fi
done
or if you prefer,
shopt -s extglob
line=grub2-systemd-sleep-plugin-2.02-153.1-foo-1
while [[ -n "$line" ]]
do case "$line" in
+([0-9.])-*) line="${line#*-}" ;;
+([0-9.])) break ;;
+([[:alnum:]])-*) echo "${line%%-*}"
line="${line#*-}" ;;
+([[:alnum:]])) echo "$line"
break ;;
*) echo "How did I get here?" ;;
esac
done
I would like to check in bash if line starts with digit then put those lines in a separate file. I tried ^[[0-9]] but it doesn't work.
Here is the code which I tried:
myFailedFile=/tmp/1.txt
myTestsFile:
177711 TESTING ...yahoo.tests.calendar.resources.scheduler.1
854756 TESTING ...yahoo.tests.calendar.resources.scheduler.2
* 2102637 DONE ...yahoo.tests.mail.contacts.add.3
while read line
do
if ( [[ ${line} = "^[[0-9]]"* ]] && [[ ${line} = *".tests."* ]] ); then
echo -e "${line}\r" >> ${myFailedFile}
fi
done <"${myTestsFile}"
Expected output of myFailedFile:
177711 TESTING ...yahoo.tests.calendar.resources.scheduler.1
854756 TESTING ...yahoo.tests.calendar.resources.scheduler.2
The correct operator to use regex in Bash script is =~. Moreoever you don't need to double [ in range of characters. Try this:
while read line
do
if ( [[ ${line} =~ ^[0-9] ]] && [[ ${line} = *".tests."* ]] ); then
echo -e "${line}\r" >> ${myFailedFile}
fi
done <"${myTestsFile}"
Edit:
But you don't need a Bash loop for that job. You can do it with a sed one-liner:
sed '/^[0-9].*\.tests\./!d' "${myTestsFile}" > myFailedFile
Explanations(from right to left):
!d: do not delete
/^[0-9].*\.tests\./: all lines that start with one or more digits and that contain .tests. string
Without using regex you can use glob as this:
[[ $line = [0-9]* ]] && [[ $line = *".tests."* ]]
[0-9]* matches a string start start with digits
*".tests."* matches a string that contains .tests.
you can use
if [[ ${line} =~ ^[0-9] && ${line} =~ ".tests." ]] ; then
or
if [[ ${line} == [0-9]* && ${line} == *".tests."* ]] ; then
I need to make a script that iterates through a list of parameters and checks/counts if the parameter starts with an uppercase letter. I have some starter code but I am stuck and would appreciate any help!
Several notes:
You're missing the =~ operator for a regular expression
Your if is not ended by a fi.
Using [A-Z] doesn't work in all locales, and is needlessly fragile. Some collation orders are of the form AaBbCcDd, and thus A-Z contains a, b, etc; [[:upper:]] is guaranteed to do the right thing everywhere.
Unquoted $# behaves exactly the same as unquoted $*. If you want to correctly honor the quoting and escaping used when your function was first called, use "$#", quoted.
Consider instead:
#!/bin/bash
(( "$#" )) || { echo "Error: No arguments given" >&2; exit 1; }
re='^[[:upper:]]' # store regex in a variable for compatibility with old bash releases
for word in "$#"; do
[[ $word =~ $re ]] && ((++count))
done
echo "$count arguments started with upper-case characters"
Alternately, by using a case statement you can avoid requiring bash, and also check for other types:
for word in "$#"; do
case $word in
[[:upper:]]*) (( ++upper_count )) ;;
[[:lower:]]*) (( ++lower_count )) ;;
[[:digit:]]*) (( ++digit_count )) ;;
esac
done
echo "Found $upper_count arguments starting with upper-case letters"
echo "Found $lower_count arguments starting with lower-case letters"
echo "Found $digit_count arguments starting with digits"
#! /bin/bash
if [ $# -eq 0 ]; then
echo Error
exit 1
fi
COUNT=`echo "$#" | tr ' ' '\n' | grep "^[A-Z]" | wc -l`
echo $COUNT
I'm unfamiliar with bash scripting. I wrote a script check arguments. the code is:
for (( i=1; i<=4; i++ ))
do
if ! [[ "$"$i =~ .*[^0-9].* ]]; then
echo "bad input was $i"
fi
done
Actually i want to split non numerical arguments, But it seems that "$"$i is wrong because the answer is always true or false independent of arguments.
can anybody tell me what is the mistake?
You seem to be trying to use indirect parameter expansion.
for (( i=1; i<=4; i++ ))
do
if ! [[ ${!i} =~ .*[^0-9].* ]]; then
echo "bad input was $i"
fi
done
However, it's cleaner to just iterate over the parameters directly, rather than over their position:
for arg in "${#:1:4}"; do
if ! [[ $arg =~ .*[^0-9].* ]]; then
echo "bad input was $arg"
fi
done
If condition should be like this:
if [[ ! "$i" =~ [^0-9] ]]; then
OR remove 2 negatives:
if [[ "$i" =~ [0-9] ]]; then
OR use glob:
if [[ "$i" == *[0-9]* ]]; then
Which means $i contains a digit 0-9
Update: Based on your comments it looks like you are looking for BASH variable indirection like this script check-num.sh:
#!/bin/bash
for (( i=1; i<=$#; i++ )); do
[[ "${!i}" != *[0-9]* ]] && echo "bad input was ${!i}"
done
You can run this script as: ./check-num.sh 1 2 x 4 a
Note how ${!i} syntax is being used here to access the variable's $1, $2, $3 etc that is called BASH variable indirection. You shouldn't use $$i for this purpose.
As per BASH manual:
If the first character of parameter is an exclamation point, a level of variable indirection is introduced. Bash uses the value of the variable formed from
the rest of parameter as the name of the variable; this variable is then expanded and that value is used in the rest of the substitution, rather than the
value of parameter itself.
Use something like this :
for i in "$#"; do
[[ $i =~ .*[^0-9].* ]] || echo "bad input was $i"
done
N.B : It's not necessary to use doubles quotes arround the variable with the [[ internal instruction.
When given a string I want to search for a substring which matches two characters (9&0. 0 should be the last character in that substring) and exactly two characters in between them
string="asd20 92x0x 72x0 YX92s0 0xx0 92x0x"
#I want to select substring YX92s0 from that above string
for var in $string
do
if [[ "$var" == *9**0 ]]; then
echo $var // Should print YX92s0 only
fi
done
Obviously this above command doesn't work.
You match each element against the pattern *9??0. There are several ways you can do this; here's one that uses the string to set the positional parameters in a subshell, then iterates over them in a for loop:
( set -- $string
for elt; do [[ $elt == *9??0 ]] && { echo "found"; exit; }; done )
string="asd20 92x0x 72x0 X92s0 0xx0"
if [[ $string =~ [[:space:]].?9.{2}0[[:space:]] ]]; then
echo "found"
fi
Or better, taking advantage of word spliting :
string="asd20 92x0x 72x0 X92s0 0xx0"
for s in $string; do
if [[ $s =~ (.*9.{2}0) ]]; then
echo "${BASH_REMATCH[1]} found"
fi
done
This is regex with bash.