Getting category when given the variable from external file to shell script

Hi, I have a script that interacts with a config file in the format:

[CategoryA]
file1.txt
file2.txt
 
[CategoryB]
file3.txt
file4.txt
file5.txt
 
[CategoryC]
 
[CategoryD]
file6.txt

I would like to return the Category, when given the file name.

FILENAME=file4.txt
CATEGORY=?

Anyone know how to do this?

Nothing to it but to look through the file and check.

#!/bin/ksh

TOFIND="file4.txt"
CATEGORY=""

while read LINE
do
        [ -z "$LINE" ] && continue

        if [ "${LINE:0:1}" == "[" ]
        then
                CATEGORY="${LINE:1:$((${#LINE}-2))}"
                continue
        fi

        if [ "$LINE" == "$TOFIND" ]
        then
            echo "category is $CATEGORY"
            break
        fi
done < conf.file

Should also work in BASH.

Thank you for the quick reply. I get the following output:

 
./script.sh[10]: "${LINE:0:1}": bad substitution
 

:confused:

I copy-pasted that from the working script so it shouldn't contain typos. Did you type that in or copy it?

What is your shell? What is your system?

I copy/pasted.

Bash ver 3.00.16(1)
Running on AIX5.1

That's very strange. The "${VAR:OFFSET:LENGTH}" syntax works even in bash 2.0, let alone 3.0. It even works in ASH. I don't know how they butchered it to get it working in AIX. Are you running it as /bin/bash or /bin/sh ?

Are you sure you don't have DASH installed? That's a BASH-alike that throws up on that syntax.

If you have ksh available could you try using it instead.

Sorry, I should have been more explicit.

I'm using bash, but the script is using ksh (I did copy/paste your example).

I changed the first line to reference bash and it does work, unfortunately the rest of my script uses ksh and that can't change for various reasons.

I see here:

[Edit: You are only allowed to post URL once you have at least 5 posts. ]
h t t p : // w w w .issociate.de/board/post/265609/ksh_variable_substitution_quandry.html

that various versions of ksh can't use that substitution syntax. I've been trying to figure out the version of ksh we have but can't seem to ...

You must have ksh88 for it not to support : substring syntax.

here are the hacks you can do to get something like a substring in ksh88.

---------- Post updated at 02:22 PM ---------- Previous update was at 02:16 PM ----------

using the substring function from that thread:

#!/bin/ksh

TOFIND="file4.txt"
CATEGORY=""

function substring
{
    typeset string="$1" out
    typeset -i offset=$2 length=$3

    while (( offset > 0 ))
    do
        string="${string#?}"
        (( offset = offset - 1 ))
    done

    while (( length > 0 ))
    do
        out="$out${string%${string#?}}"
        string="${string#?}"
        (( length = length - 1 ))
    done

    print "$out"
}

while read LINE
do
        [ -z "$LINE" ] && continue

        if [ $(substring "${LINE}" 0 1) == "[" ]
        then
                CATEGORY="$(substring "$LINE" 1 $((${#LINE}-2)))"
                continue
        fi

        if [ "$LINE" == "$TOFIND" ]
        then
            echo "category is $CATEGORY"
            break
        fi
done < conf.file 

Warning, this may be slow.

I now have pdksh installed to test compatibility with truly obnoxiously old shells... I really find it hard to imagine a shell that doesn't have the : syntax. did they just use the cut external all the time or what?

1 Like

Fantastic, thank you very much for your help.

An alternative with regular variable expansion:

case $LINE in
  \[*)
      CATEGORY=${LINE#\[Category}
      CATEGORY=${CATEGORY%]} ;;
  $TOFIND)
      echo "category is $CATEGORY"
      break          
esac

One last question relevent to this post:

If the entry is NOT found, how can I echo "not found"?

This seems like it should be profoundly simple, yet I've been trying to get it to work and I'm stumped. Any ideas?

---------- Post updated 01-26-11 at 08:52 AM ---------- Previous update was 01-25-11 at 04:47 PM ----------

Any ideas?

I've been trying to determine EOF but can't find a way.

Should I just do a grep before looping and skip the loop if it's not present?

If the entry is there as a comment however, it would cause problems....

:wall:

You could use a boolean:

TOFIND="file4.txt"
CATEGORY=
FOUND=false
while read line
do
  case $line in
    \[*)
        CATEGORY=${line#\[Category}
        CATEGORY=${CATEGORY%]} ;;
    $TOFIND)
        echo "category is $CATEGORY"
        FOUND=true
        break          
  esac
done < conf.file
if ! $FOUND; then
  echo "not found"
fi