3

I have strings like this

/home/rm/home-scripts/originals/audicerttest/incoming/TEST040511.txt
/home/rm/home-scripts/originals/audicerttest2/incoming/TEST040512.txt
/home/rm/home-scripts/originals/audicerttest3/incoming/TEST040513.txt

etc..I want to extract strings 'audicerttest/incoming', audicerttest2/incoming' etc into a shell variable and use it later in the script. I tried something like this.

for file in `find ${ROOT}/* -type f | grep -v -f test.txt`
do
let count++
echo ${count}: ${file}
echo ${file} | eval $(awk '{split($0,a,"/"); print "abc=a[6]/a[7]"}' < /dev/null)
echo abc====$abc
done

but its not giving any output for abc.

5 Answers 5

7

There are a number of issues, but let's isolate problems and tackle them one at a time.

Given - Raw string:

/home/rm/home-scripts/originals/audicerttest/incoming/TEST040511.txt

Desired Output - You want this part to be saved in a variable:

audicerttest/incoming

How-To - This will do it:

string="/home/rm/home-scripts/originals/audicerttest/incoming/TEST040511.txt"
parsed=$(awk 'BEGIN{FS=OFS="/"} {print $6, $7}' <<< ${string})

In general, suppose you have a file called input_file.txt:

/home/rm/home-scripts/originals/audicerttest/incoming/TEST040511.txt
/home/rm/home-scripts/originals/audicerttest2/incoming/TEST040512.txt
/home/rm/home-scripts/originals/audicerttest3/incoming/TEST040513.txt

You can do:

awk 'BEGIN{FS=OFS="/"} {print $6, $7}' input_file.txt > parsed_vars.txt

And parsed_vars.txt will contain:

audicerttest/incoming
audicerttest2/incoming
audicerttest3/incoming

Some explanations:

  • parsed=$(...) - spawn a subshell and save the output to stdout within that subshell to the variable parsed
  • awk 'BEGIN{FS=OFS="/"} - invoke awk and set delimiter as / for both input and output.
  • {print $6, $7}' - based on the format of your raw strings, you want to print the 6th (audicerttest) and the 7th (incoming) fields.
  • <<< ${string} is the notation for using herestring
  • input_file.txt > parsed_vars.txt - read from specified input file, and redirect output to an output file.
Sign up to request clarification or add additional context in comments.

Comments

2

Here's a pure bash solution, not using any overkill awk and not using any evil eval and not using any subshells:

You have this string:

string="/home/rm/home-scripts/originals/audicerttest/incoming/TEST040511.txt"

You want a string that contains the 5th and 6th fields (where separation is /) in a variable parsed. Let's go:

IFS=/ a=( $string ) printf -v parsed '%s/%s' "${a[@]:5:2}"

Comments

1
echo ${file} | eval $(awk '{split($0,a,"/"); print "abc=a[6]/a[7]"}' < /dev/null)

Okay, a couple of problems here.

awk is reading from /dev/null, which doesn't make any sense, guess you want to process the filename:

echo {$file} | awk ... 

"a[6]" is the string a[6], no substitution is made.

Now eval the whole thing:

eval $(echo $file | awk '{split($0,a,"/"); print "abc="a[6]"/"a[7]""}')

Finally, eval is evil, why don't you directly set the variable?

abc=$(echo $file | awk '{split($0,a,"/"); print a[6]"/"a[7]}')

On a personal note, I thing this is a bit more clear:

 cut -d / --output-delimiter / -f6,7

3 Comments

The main problem in your method is the useless use of eval. eval is evil! Not mentioning the useless uses of subshells.
I was just updating my answer... He is using an inefficient tool for the task, but (I hope) he's asking about why it didn't work, an not just asking for an other solution. So, no idea why the downvote.
I'm a total newbie to Shell. I agree there are too many mistakes. Thanks for correcting those.
1

With only bash arrays, you could do the following:

Assuming:

path=/home/rm/home-scripts/originals/audicerttest/incoming/TEST040511.txt

Then:

IFS=/ split=(${path})
path_part="${split[5]}/${split[6]}"

$split will be an array, with element 0 empty, element one home, element 2 rm, etc. With that you just need to concatenate the elements you want to get the part you like.

Comments

0

Nobody has suggested simple parameter expansion to manipulate the strings. I'm assuming that the first 4 directories are constant

while read path; do
    dirname=$(dirname $path)
    abc=${dirname#/home/rm/home-scripts/originals/}
    echo "abc===$abc"
done < filename

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.