I'm using a bash script to identify where something is used and then find a corresponding reference (name).
The script is:
#!/bin/bash
echo "running, searching for instances of ${1:0:1}/$1"
for i in ls -d Module*; do
if [ -d "$i" ]; then
if [ -f $i/003.Design/003.Data.efx ]; then
if grep -qe "Module-0000/003.Design/005.Types/${1:0:1}/$1" $i/003.Design/003.Data.efx; then
echo $i $i/003.Design/003.Data.efx
grep -B 4 "Module-0000/003.Design/005.Types/${1:0:1}/$1" $i/003.Design/003.Data.efx | grep "name"
fi
fi
fi
done
I'm trying to change it to:
#!/bin/bash
echo "running, searching for instances of ${1:0:1}/$1"
for i in ls -d Module*; do
if [ -d "$i" ]; then
if [ -f $i/003.Design/003.Data.efx ]; then
if grep -qe "Module-0000/003.Design/005.Types/${1:0:1}/$1" $i/003.Design/003.Data.efx; then
echo $i $i/003.Design/003.Data.efx
for j in `grep -B 4 "Module-0000/003.Design/005.Types/${1:0:1}/$1" $i/003.Design/003.Data.efx | grep "name"` ; do
echo $j
done
fi
fi
fi
done
When I make the above change to iterate through the results, the results are all screwed up. I suspect that my use of for
is incorrect.
I should note that the results before the change are:
$ ./findEllipseType.sh AveragePrice
running, searching for instances of A/AveragePrice
Module-3110 Module-3110/003.Design/003.Data.efx
<ownedAttribute xmi:id="_P7sUcAg7EdysLcyAWbYneA" name="EstPrice">
Module-3140 Module-3140/003.Design/003.Data.efx
<ownedAttribute xmi:id="_Z2v4IaW-EduyI4lEFgFo8g" name="StoresSalePrice">
<ownedAttribute xmi:id="_bpCVJaW-EduyI4lEFgFo8g" name="StoresSalePrice">
<ownedAttribute xmi:id="_j0crsMnVEeOm9cfLF6jryw" name="EstPrice">
Module-3210 Module-3210/003.Design/003.Data.efx
<ownedAttribute xmi:id="_dYMlpaW-EduyI4lEFgFo8g" name="GrossPriceP">
<ownedAttribute xmi:id="_duQVQqW-EduyI4lEFgFo8g" name="GrossPriceP">
<ownedAttribute xmi:id="_dujQI6W-EduyI4lEFgFo8g" name="CurrNetPrP">
<ownedAttribute xmi:id="_eNZISqW-EduyI4lEFgFo8g" name="GrossPriceP">
<ownedAttribute xmi:id="_eNi5QKW-EduyI4lEFgFo8g" name="PrevGpP">
<ownedAttribute xmi:id="_eNsqQqW-EduyI4lEFgFo8g" name="CurrNetPrP">
<ownedAttribute xmi:id="_eNsqSqW-EduyI4lEFgFo8g" name="PrevNetPrP">
<ownedAttribute xmi:id="_fRV4kqW-EduyI4lEFgFo8g" name="CurrNetPrP">
<ownedAttribute xmi:id="_fRV4mqW-EduyI4lEFgFo8g" name="GrossPriceP">
<ownedAttribute xmi:id="_fgsjMqW-EduyI4lEFgFo8g" name="EstPrice">
<ownedAttribute xmi:id="_fg1tJaW-EduyI4lEFgFo8g" name="ActGrossPr">
Module-3560 Module-3560/003.Design/003.Data.efx
<ownedAttribute xmi:id="_xM44IKW-EduyI4lEFgFo8g" name="UnitPrice">
<ownedAttribute xmi:id="_xOYF8KW-EduyI4lEFgFo8g" name="UnitPrice">
<ownedAttribute xmi:id="_xdbOkKW-EduyI4lEFgFo8g" name="AmendPrice">
But when I've made the change it appears as (truncated):
$ ./findEllipseType.sh AveragePrice
running, searching for instances of A/AveragePrice
Module-3110 Module-3110/003.Design/003.Data.efx
<ownedAttribute
xmi:id="_P7sUcAg7EdysLcyAWbYneA"
name="EstPrice">
Module-3140 Module-3140/003.Design/003.Data.efx
<ownedAttribute
xmi:id="_Z2v4IaW-EduyI4lEFgFo8g"
name="StoresSalePrice">
<ownedAttribute
xmi:id="_bpCVJaW-EduyI4lEFgFo8g"
name="StoresSalePrice">
<ownedAttribute
xmi:id="_j0crsMnVEeOm9cfLF6jryw"
name="EstPrice">
Module-3210 Module-3210/003.Design/003.Data.efx
<ownedAttribute
xmi:id="_dYMlpaW-EduyI4lEFgFo8g"
Looking through the results it appears as though the for in
is using a space delimiter when I want it to use a line delimiter. How do I change this please?
tl;dr:
for i in ls -d Module*; do
to for i in Module*/;do
for j in `grep -B 4 "Module-0000/003.Design/005.Types/${1:0:1}/$1" $i/003.Design/003.Data.efx | grep "name"` ; do
echo $j
done
with
while IFS= read -r j; do
echo "$j"
done < <(grep -B 4 "Module-0000/003.Design/005.Types/${1:0:1}/$1" "$i/003.Design/003.Data.efx" | grep "name")
See below for a full discussion.
for i in ls -d Module*; do
will simply enumerate tokens ls
, -d
and (possibly expanded) Module*
instead of enumerating the output from an ls
command.
To correct that immediate problem, you'd have to use command substitution (for i in $(ls -d Module*; do)
), but that is not advisable, because using globbing (pathname expansion) directly is the robust, proper solution: for i in Module*/; do
Similarly, it's not advisable to use a for
loop to parse command output line by line, because the output is subject to word splitting, among other shell expansions.
Effectively, the for
loop enumerates whitespace-separated tokens rather than full lines.
Using a while
loop with IFS= read -r
, with input provided via process substitution, is the right approach - it ensures that lines are read unmodified.
Also, it's generally advisable to double-quote variable references to avoid unwanted shell expansions.
A revised form of your code is therefore:
shopt -s nullglob # ensure that a glob matching nothing expands to empty string
for i in Module*/; do
if [[ -f "$i/003.Design/003.Data.efx" ]]; then
if grep -qe "Module-0000/003.Design/005.Types/${1:0:1}/$1" "$i/003.Design/003.Data.efx"; then
echo "$i $i/003.Design/003.Data.efx"
while IFS= read -r j; do
echo "$j"
done < <(grep -B 4 "Module-0000/003.Design/005.Types/${1:0:1}/$1" "$i/003.Design/003.Data.efx" | grep "name")
fi
fi
done
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With