Page 1 of 1

Shell Script Special Character Test

Posted: 27 Nov 2014, 01:15
by Bogomips
Quick way of testing if string ends in '*'.

Unsuccessful Efforts without Quoting

Code: Select all

#set -x
echo $1
s=$1A
if [ "${s##*\*}" = "A" ]; then echo $1 "Ends in *"; exit; fi
echo $1 No Match

guest@porteus:~$ touch abcd abce
guest@porteus:~$ ls abc*
abcd  abce
guest@porteus:~$ sh p10/Por/ast.sh abc*
abcd
abcd No Match
guest@porteus:~$ rm abc*
guest@porteus:~$ sh p10/Por/ast.sh abc*
abc*
abc* Ends in *

set -x
echo $1
s=$1A
if [ "${s##*\*}" = "A" ]; then echo $1 "Ends in *"; exit; fi
echo $1 No Match

guest@porteus:~$ touch abcd abce
guest@porteus:~$ ls abc*        
abcd  abce

guest@porteus:~$ sh p10/Por/ast.sh abc*        
+ echo abcd
abcd
+ s=abcdA
+ '[' abcdA = A ']'
+ echo abcd No Match
abcd No Match

guest@porteus:~$ rm abc*
guest@porteus:~$ sh p10/Por/ast.sh abc*
+ echo 'abc*'
abc*
+ s='abc*A'
+ '[' A = A ']'
+ echo 'abc*' 'Ends in *'
abc* Ends in *
+ exit

Code: Select all

guest@porteus:~$ touch abcd abce
guest@porteus:~$ ls abc*
abcd  abce
guest@porteus:~$ sh p10/Por/ast.sh "abc*"
abcd abce
abcd abce Ends in *
guest@porteus:~$ sh p10/Por/ast.sh 'abc*'
abcd abce
abcd abce Ends in *

Re: Shell Script Special Character Test

Posted: 27 Nov 2014, 01:34
by brokenman
x="abcd*"

[[ `echo $x | awk '{print substr($0,length,1)}'` = "*" ]] && echo yes
[[ `echo $x | awk '$0=$NF' FS=` = "*" ]] && echo yes
[[ "${x: -1}" = "*" ]] && echo yes

Re: Shell Script Special Character Test

Posted: 29 Nov 2014, 20:09
by Bogomips
brokenman wrote:x="abcd*"

[[ `echo $x | awk '{print substr($0,length,1)}'` = "*" ]] && echo yes
[[ `echo $x | awk '$0=$NF' FS=` = "*" ]] && echo yes
[[ "${x: -1}" = "*" ]] && echo yes
Thanks for input.

Code: Select all

guest@porteus:~$ touch abc*  abc*xyz*  abcde  abcef  awxybcz  axyzbc
guest@porteus:~$ ls a*
abc*  abc*xyz*  abcde  abcef  awxybcz  axyzbc
  • [[ `echo $x | awk '{print substr($0,length,1)}'` = "*" ]] && echo yes Doesn't work.

    Code: Select all

    guest@porteus:~$ x=tuv*
    guest@porteus:~$ [[ `echo $x | awk '{print substr($0,length,1)}'` = "*" ]] && echo yes || echo no
    yes
    guest@porteus:~$ x=abc*f*
    guest@porteus:~$ [[ `echo $x | awk '{print substr($0,length,1)}'` = "*" ]] && echo yes || echo no
    no
    
    • [[ `echo $x | awk '$0=$NF' FS=` = "*" ]] && echo yes
      No idea how this is supposed to function. Doesn't work.

      Code: Select all

      guest@porteus:~$ x=tuv*
      guest@porteus:~$ [[ `echo $x | awk '$0=$NF' FS=` = "*" ]] && echo yes || echo no
      yes
      guest@porteus:~$ x=abc*f*
      guest@porteus:~$ [[ `echo $x | awk '$0=$NF' FS=` = "*" ]] && echo yes || echo no
      no
      
      • [[ "${x: -1}" = "*" ]] && echo yes Simplest Works.

        Code: Select all

        guest@porteus:~$ x=tuv*
        guest@porteus:~$ [[ "${x: -1}" = "*" ]] && echo yes || echo no
        yes
        guest@porteus:~$ x=abc*f*
        guest@porteus:~$ [[ "${x: -1}" = "*" ]] && echo yes || echo no
        yes
        guest@porteus:~$ x=abc*
        guest@porteus:~$ [[ "${x: -1}" = "*" ]] && echo yes || echo no
        yes
        guest@porteus:~$ x=abc*ef
        guest@porteus:~$ [[ "${x: -1}" = "*" ]] && echo yes || echo no
        no
        guest@porteus:~$ x=abc
        guest@porteus:~$ [[ "${x: -1}" = "*" ]] && echo yes || echo no
        no
        guest@porteus:~$ x=ab*d*e
        guest@porteus:~$ [[ "${x: -1}" = "*" ]] && echo yes || echo no
        no
        
        :good:

      Re: Shell Script Special Character Test

      Posted: 01 Dec 2014, 09:22
      by brokenman
      There are other variations where some of these won't work too, but in your example you give only one special character on the end and don't stipulate any conditions.

      Re: Shell Script Special Character Test

      Posted: 27 Dec 2014, 01:23
      by Bogomips
      brokenman wrote:There are other variations where some of these won't work too, but in your example you give only one special character on the end and don't stipulate any conditions.
      Not stipulating any conditions, had the added benefit of improving my understanding of what's going on here. :)

      Stipulating condition: x is argument to shell script ast.sh, and may or may not be a wildcard argument, which has to be detected.

      Code: Select all

      [[ "${1: -1}" = "*" ]] && echo yes || echo no
      
        • Code: Select all

          guest@porteus:~$ sh ast.sh tuv*     
          yes
          guest@porteus:~$ sh ast.sh abc*f*
          no
          guest@porteus:~$ sh ast.sh abc*
          yes
          guest@porteus:~$ sh ast.sh abc*ef
          no
          guest@porteus:~$ sh ast.sh abc
          no
          guest@porteus:~$ sh ast.sh ab*d*e
          no
          guest@porteus:~$ sh ast.sh ab*
          yes
          guest@porteus:~$ sh ast.sh abcd*
          no
          guest@porteus:~$ sh ast.sh a*
          yes
          guest@porteus:~$ sh ast.sh a*y*
          yes
          guest@porteus:~$ sh ast.sh aw*
          no
          guest@porteus:~$ sh ast.sh ax*
          no
          
          • The four instances where script fails to come up to expectation, can be tweaked by enclosing argument in quotes, which presumably inhibits pathname expansion.

            Code: Select all

            guest@porteus:~$ sh ast.sh "abc*f*"
            yes
            guest@porteus:~$ sh ast.sh "abcd*"
            yes
            guest@porteus:~$ sh ast.sh "aw*"
            yes
            guest@porteus:~$ sh ast.sh "ax*"
            yes
            
            • Final condition to stipulate, is that wildcard argument not be quoted. In this case the shell script has no control, as it is the shell, in which script is run, which decides wildcard substitution:

              Code: Select all

              guest@porteus:~$ touch abc*  abc*xyz*  abcde  abcef  awxybcz  axyzbc
              guest@porteus:~$ touch abcgh
              guest@porteus:~$ touch abc*ij
              guest@porteus:~$ ls a*
              abc*  abc*ij  abc*xyz*  abcde  abcef  abcgh  awxybcz  axyzbc
              guest@porteus:~$ sh ast.sh abc*
              yes
              guest@porteus:~$ set -f		#Disable pathname expansion.
              guest@porteus:~$ ls a*
              /bin/ls: cannot access a*: No such file or directory
              guest@porteus:~$ sh ast.sh abc*
              yes
              guest@porteus:~$ sh ast.sh abc*f*
              yes
              guest@porteus:~$ sh ast.sh abcd*
              yes
              guest@porteus:~$ sh ast.sh aw*
              yes
              guest@porteus:~$ sh ast.sh ax*
              yes
              
              However, there is no point in disallowing pathname expansion as it defeats the whole purpose of the exercise.
              • The argument abc* could always be detected, because the file abc* was always the first parameter following pathname expansion.

                Code: Select all

                guest@porteus:~$ rm abc*
                guest@porteus:~$ set +f		#Using + rather than - causes option to be turned off.
                guest@porteus:~$ ls a*
                abc*ij  abc*xyz*  abcde  abcef  abcgh  ast.sh  awxybcz  axyzbc
                guest@porteus:~$ sh ast.sh abc*
                no
                guest@porteus:~$ ls abc*
                abc*ij  abc*xyz*  abcde  abcef  abcgh
                
                With the file abc*ij as first parameter following pathname expansion, the argument abc* cannot be deduced to have a wildcard termination.
                • Looking at this next case, am not able to work out $@ (unquoted expansion of @) in second instance:

                  Code: Select all

                  ast.sh
                  #set -x
                  #set -f
                  [[ "${1: -1}" = "*" ]] && echo yes || echo no
                  echo '$1='"$1"
                  echo '$#='$#
                  echo Positional Parameters '$@': $@
                  echo Positional Parameters '"$@"': "$@"
                  echo $@ | awk '{print "Positional Params $@ (awk): "$0}'
                  ______________________________________________________________________________
                  guest@porteus:~$ touch abc*ij  abc*xyz*  abcde  abcef  abcgh
                  guest@porteus:~$ ls a*
                  abc*ij  abc*xyz*  abcde  abcef  abcgh  ast.sh
                  guest@porteus:~$ sh ast.sh abc*
                  no
                  $1=abc*ij
                  $#=5
                  Positional Parameters $@: abc*ij abc*xyz* abcde abcef abcgh
                  Positional Parameters "$@": abc*ij abc*xyz* abcde abcef abcgh
                  Positional Params $@ (awk): abc*ij abc*xyz* abcde abcef abcgh
                  guest@porteus:~$ set -f
                  guest@porteus:~$ touch abc*
                  guest@porteus:~$ ls a*
                  /bin/ls: cannot access a*: No such file or directory
                  guest@porteus:~$ set +f
                  guest@porteus:~$ ls a*
                  abc*  abc*ij  abc*xyz*  abcde  abcef  abcgh  ast.sh
                  guest@porteus:~$ sh ast.sh abc*
                  yes
                  $1=abc*
                  $#=6
                  Positional Parameters $@: abc* abc*ij abc*xyz* abcde abcef abcgh abc*ij abc*xyz* abcde abcef abcgh
                  Positional Parameters "$@": abc* abc*ij abc*xyz* abcde abcef abcgh
                  Positional Params $@ (awk): abc* abc*ij abc*xyz* abcde abcef abcgh abc*ij abc*xyz* abcde abcef abcgh
                  
                In conclusion, under the condition that the script is always invoked with one argument, it is safe to say that there is a wildcard in the argument, should the number of positional parameters "$#" exceed one. However with just one possitional parameter it looks like there is no way of telling if this is resulting from a wildcard in the argument or from the argument proper.