Shell substitution variable, err in [output] - shell

looking for some help here. I am seeing the below issue
y=1
j$y=`cat /home/devteam/auppu/new_ig_1|head -n $y`
ksh: j1=5555555555555555: not found
i have no issue when i cat on the file,like below
cat /home/devteam/auppu/new_ig_1|head -n $y
5555555555555555

The simplest way to do this is using an indexed array, like so:
y=1
j[$y]=`cat /home/devteam/auppu/new_ig_1|head -n $y`
echo ${j[$y]}
This way you can store multiple invocations of the cat command in your loop into the associative array referenced by the j variable.

You might have to do something like
y=1
x=j${y}
x=`cat /home/devteam/auppu/new_ig_1|head -n $y`
echo $x
You would need to create an intermediate variable (x in this case) and then assign to it the results of your cat command

Related

sed not parsing variable

I'm stuck with a bash script here...
I have variables:
hostname1="sxxx" hostname2="vbbbb" hostname3="sggg" hostname4="aaa" ...
I'm trying to change the 12th line of every files in a folder with the host-name variables.
The files are server1.txt server2.txt server3.txt server4.txt ...
I'm trying to do this with a while loop:
i=1
imax=1
while [[ $i -le 20 ]]
do
sed -i "12s/.*/$hostname$imax/" server$((imax)).txt
(( i++ ))
(( imax++ ))
if [[ imax -eq 21 ]]
then
imax=1
fi
done
what I want to do with sed is to concatenate the word host-name with imax and then use it as variable.
Maybe with this I'm clear enough:
$hostname=hostname$imax; //for exammple
sed -i "12s/.*/$hostname/" server$((imax)).txt // i need here the variable $hostname to have the content "sxxx"
You achieve this by using indirect parameter expansion,
${!var}
Here, var - is a dynamically generated variable name.
Try this:
sed -i "12s/.*/${!hostname}/" server$((imax)).txt
Example:
$ hostname1="sat"
$ i=1
$ hostval="hostname$i"
$ echo ${!hostval}
sat
I'd use the following. Use change, instead of switch in sed. Then strong quote my sed, and unquote my variables.
for i in {1..20}; do
eval h='$'hostname$i
sed -i '12c'$h'' server$i.txt
done
Bash 3 and over supports number ranges in a for looop, easier than your while loop. I also have no idea what you are doing with imax instead of just i, b/c you exit at 20, but change imax value to 1... which it will never use.
edit: b/c I misread
Basically, your problem comes from a variable interpretation.
Try using sed >=4.2.2, should work with your code.

Issue with Expression in For Loop - Bash

I am trying to loop through a list of servers and rather than manually enter each one in a text file, I wanted to use an expression.
Example:
[user#server001 ~]$ for i in server{001..010} ; do echo $i ; done
server001
server002
server003
server004
server005
server006
server007
server008
server009
server010
That Produces the desired result. However when I put server{001..010} into a .txt file and try to do the same thing, it doesn't work:
[user#server001 ~]$ cat server_test2.txt
server{001..010}
[user#server001 ~]$ for i in `cat server_test2.txt` ; do echo $i ; done
server{001..010}
As you can see it doesn't actually handle the expression the way I'd like it to.
Any ideas how I can extrapolate from a txt file with multiple lines of servers using the expression method? {001..010}
you could use eval; like this:
list=$(cat server_test2.txt)
CMD="for i in $list ; do echo \$i; done"
eval $CMD

How can I get the length of all arguments given to a function in bash?

I'd like to get the length of the string that I get when i use "$*" in my function.
I tried:
echo ${#"$*"}
and
echo ${#"*"}
both gave me a bad substitution error.
I don't think you can do it in a single command. However, this seems to work:
#!/bin/bash
a="$#"
echo "${#a}"
Using a temporary variable is the only one basic way, and you need to unset IFS or set it to empty string to prevent spaces in between. And use $* not $# for it would give you spaces in between:
IFS= eval "__=\"\$*\""
echo "${#__}"
Another way is to loop through all strings:
L=0; for __; do (( L += ${#__} )); done
echo "$L"
You can use one of the following.
expr length "$*"
echo "$*" | awk '{print length}'
$# holds the number of positional parameters passed to the function.
Try it:
#!/bin/bash
t() {
echo "num args=$#"
echo "all $*"
}
t "$#"

SED, using variables and in with an array

What I am trying to do is run the sed on multiple files in the directory Server_Upload, using variables:
AB${count}
Corresponds, to some variables I made that look like:
echo " AB1 = 2010-10-09Three "
echo " AB2 = 2009-3-09Foo "
echo " AB3 = Bar "
And these correspond to each line which contains a word in master.ta, that needs changing in all the text files in Server_Upload.
If you get what I mean... great, I have tried to explain it the best I can, but if you are still miffed I'll give it another go as I found it really hard to convey what I mean.
cd Server_Upload
for fl in *.UP; do
mv $fl $fl.old
done
count=1
saveIFS="$IFS"
IFS=$'\n'
array=($(<master.ta))
IFS="$saveIFS"
for i in "${array[#]}"
do
sed "s/$i/AB${count}/g" $fl.old > $fl
(( count++ ))
done
It runs, doesn't give me any errors, but it doesn't do what I want, so any ideas?
Your loop should look like this:
while read i
do
sed "s/$i/AB${count}/g" $fl.old > $fl
(( count ++ ))
done < master.ta
I don't see a reason to use an array or something similar. Does this work for you?
It's not exactly clear to me what you are trying to do, but I believe you want something like:
(untested)
do
eval repl=\$AB${count}
...
If you have a variable $AB3, and a variable $count, $AB${count} is the concatenation of $AB and $count (so if $AB is empty, it is the same as $count). You need to use eval to get the value of $AB3.
It looks like your sed command is dependent on $fl from inside the first for loop, even though the sed line is outside the for loop. If you're on a system where sed does in-place editing (the -i option), you might do:
count=1
while read i
do
sed -i'.old' -e "s/$i/AB${count}/g" Server_Upload/*.UP
(( count ++ ))
done < master.ta
(This is the entire script, which incorporates Patrick's answer, as well.) This should substitute the text ABn for every occurrence of the text of the nth line of master.ta in any *.UP file.
Does it help if you move the first done statement from where it is to after the second done?

How to iterate over positional parameters in a Bash script?

Where am I going wrong?
I have some files as follows:
filename_tau.txt
filename_xhpl.txt
filename_fft.txt
filename_PMB_MPI.txt
filename_mpi_tile_io.txt
I pass tau, xhpl, fft, mpi_tile_io and PMB_MPI as positional parameters to script as follows:
./script.sh tau xhpl mpi_tile_io fft PMB_MPI
I want grep to search inside a loop, first searching tau, xhpl and so on..
point=$1 #initially points to first parameter
i="0"
while [$i -le 4]
do
grep "$str" ${filename}${point}.txt
i=$[$i+1]
point=$i #increment count to point to next positional parameter
done
Set up your for loop like this. With this syntax, the loop iterates over the positional parameters, assigning each one to 'point' in turn.
for point; do
grep "$str" ${filename}${point}.txt
done
There is more than one way to do this and, while I would use shift, here's another for variety. It uses Bash's indirection feature:
#!/bin/bash
for ((i=1; i<=$#; i++))
do
grep "$str" ${filename}${!i}.txt
done
One advantage to this method is that you could start and stop your loop anywhere. Assuming you've validated the range, you could do something like:
for ((i=2; i<=$# - 1; i++))
Also, if you want the last param: ${!#}
See here, you need shift to step through positional parameters.
Try something like this:
# Iterating through the provided arguments
for ARG in $*; do
if [ -f filename_$ARG.txt]; then
grep "$str" filename_$ARG.txt
fi
done
args=$#;args=${args// /,}
grep "foo" $(eval echo file{$args})

Resources