views:

6323

answers:

8

I need to compare strings in shell:

var1="mtu eth0"

if [ "$var1" == "mtu *" ]
then
    # do something
fi

But obviously the "*" doesn't work in Shell. Is there a way to do it?

A: 

Look into regular expressions and =~. I haven't tested it yet, but $var1 =~ "mtu .*" should work.

KernelM
shell's "test" doesn't have the "=~", does it? If only it were Perl..
n-alexander
Bash 3.1 and greater has [[ a =~ .* ]]. But* inside the quotes is wrong for 3.2 and greater without shopt -s compat31.
ephemient
+5  A: 

Shortest fix:

if [[ "$var1" = "mtu "* ]]

Bash's [[ ]] doesn't get glob-expanded, unlike [ ] (which must, for historical reasons).

Edit

Oh, I posted too fast. Bourne shell, not Bash...

if [ "${var1:0:4}" == "mtu " ]

${var1:0:4} means the first four characters of $var1.

Edit 2

Ah, sorry. Bash's POSIX emulation doesn't go far enough; a true original Bourne shell doesn't have ${var1:0:4}. You'll need something like mstrobl's solution.

if [ "$(echo "$var1" | cut -c0-4)" == "mtu " ]
ephemient
+4  A: 

Use the unix tools. The program "cut" will happily shorten a string.

if [ "$(echo $var1 | cut -c 4)" -eq "mtu " ];

... should do what you want.

mstrobl
yes, but kinda heavy
n-alexander
A: 

Or, as an example of the =~ operator:

if [[ "$var1" =~ "mtu *" ]]
ayaz
What kind of shell is that?
ADEpt
Bash 3.1 and greater has [[ a =~ .* ]]. But* inside the quotes is wrong for 3.2 and greater without shopt -s compat31.
ephemient
+3  A: 

You can call expr to match strings against regular expressions from within Bourne Shell scripts. The below seems to work:

#!/bin/sh

var1="mtu eth0"

if [ "`expr \"$var1\" : \"mtu .*\"`" != "0" ];then
  echo "match"
fi
hasseg
+1  A: 

I'd do the following:

# Removes anything but first word from "var1"
if [ "${var1%% *}" = "mtu" ] ; then ... fi

Or:

# Tries to remove the first word if it is "mtu", checks if we removed anything
if [ "${var1#mtu }" != "$var1" ] ; then ... fi
ADEpt
A: 

I like to use the case statement to compare strings.

A trivial example is

case "$input"
in
  "$variable1") echo "matched the first value" 
     ;;
  "$variable2") echo "matched the second value"
     ;;
  *[a-z]*)  echo "input has letters" 
     ;;
  '')       echo "input is null!"
     ;;
   *[0-9]*)  echo "matched numbers (but I don't have letters, otherwise the letter test would have been hit first!)"
     ;;
   *) echo "Some wacky stuff in the input!"
esac

I've done crazy things like

case "$(cat file)"
in
  "$(cat other_file)")  echo "file and other_file are the same"
      ;;
  *)  echo "file and other_file are different"
esac

And that works too, with some limitations, such as the files can't be more than a couple megabytes and the shell simply doesn't see nulls, so if one file is full of nulls and the other has none, (and neither have anything else), this test won't see any difference between the two.

I don't use the file-comparing as a serious example, only an example of how the case statement is capable of doing much more flexible string matching than is available with test or expr or other similar shell expressions.

chris
A: 

In Bourne shell,

if I want to check whether a string conatins another string:

if [ echo ${String} | grep -c ${Substr} -eq 1 ] ; then

....

Enclose echo ${String} | grep -c ${Substr} with two ` (for some reason doesn't show in the post)

To check whether the substring is at the beginning or at the end:

if [ echo ${String} | grep -c "^${Substr}" -eq 1 ] ; then ....

if [ echo ${String} | grep -c "${Substr}$" -eq 1 ] ; then ....

Sal