Shell Script Special Character Test

For discussions about programming and projects not necessarily associated with Porteus.
Post Reply
Bogomips
Full of knowledge
Full of knowledge
Posts: 2560
Joined: 25 Jun 2014, 15:21
Distribution: 3.2.2 Cinnamon & KDE5
Location: London

Shell Script Special Character Test

Post#1 by Bogomips » 27 Nov 2014, 01:15

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 *
Last edited by Bogomips on 27 Nov 2014, 01:38, edited 1 time in total.
Linux porteus 4.4.0-porteus #3 SMP PREEMPT Sat Jan 23 07:01:55 UTC 2016 i686 AMD Sempron(tm) 140 Processor AuthenticAMD GNU/Linux
NVIDIA Corporation C61 [GeForce 6150SE nForce 430] (rev a2) MemTotal: 901760 kB MemFree: 66752 kB

User avatar
brokenman
Site Admin
Site Admin
Posts: 5503
Joined: 27 Dec 2010, 03:50
Distribution: Porteus v3.2rcX all desktops
Location: Brazil
Contact:

Re: Shell Script Special Character Test

Post#2 by brokenman » 27 Nov 2014, 01:34

x="abcd*"

[[ `echo $x | awk '{print substr($0,length,1)}'` = "*" ]] && echo yes
[[ `echo $x | awk '$0=$NF' FS=` = "*" ]] && echo yes
[[ "${x: -1}" = "*" ]] && echo yes
How do i become super user?
Wear your underpants on the outside and put on a cape.

Bogomips
Full of knowledge
Full of knowledge
Posts: 2560
Joined: 25 Jun 2014, 15:21
Distribution: 3.2.2 Cinnamon & KDE5
Location: London

Re: Shell Script Special Character Test

Post#3 by Bogomips » 29 Nov 2014, 20:09

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:
      Linux porteus 4.4.0-porteus #3 SMP PREEMPT Sat Jan 23 07:01:55 UTC 2016 i686 AMD Sempron(tm) 140 Processor AuthenticAMD GNU/Linux
      NVIDIA Corporation C61 [GeForce 6150SE nForce 430] (rev a2) MemTotal: 901760 kB MemFree: 66752 kB

      User avatar
      brokenman
      Site Admin
      Site Admin
      Posts: 5503
      Joined: 27 Dec 2010, 03:50
      Distribution: Porteus v3.2rcX all desktops
      Location: Brazil
      Contact:

      Re: Shell Script Special Character Test

      Post#4 by brokenman » 01 Dec 2014, 09:22

      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.
      How do i become super user?
      Wear your underpants on the outside and put on a cape.

      Bogomips
      Full of knowledge
      Full of knowledge
      Posts: 2560
      Joined: 25 Jun 2014, 15:21
      Distribution: 3.2.2 Cinnamon & KDE5
      Location: London

      Re: Shell Script Special Character Test

      Post#5 by Bogomips » 27 Dec 2014, 01:23

      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.
                Linux porteus 4.4.0-porteus #3 SMP PREEMPT Sat Jan 23 07:01:55 UTC 2016 i686 AMD Sempron(tm) 140 Processor AuthenticAMD GNU/Linux
                NVIDIA Corporation C61 [GeForce 6150SE nForce 430] (rev a2) MemTotal: 901760 kB MemFree: 66752 kB

                Post Reply