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
Related
I need to execute series of commands inside an interactive program/utility with parameterized values. Is there a way to loop inside heredoc ? Like below .. Not sure if eval can be of any help here. Below example doesn't seem to work as the interactive doesn't seem to recognize system commands.
#!/bin/sh
list="OBJECT1 OBJECT2 OBJECT3"
utilityExecutable << EOF
for i in $list ; do
utilityCommand $i
done
EOF
Instead of passing a here-document to utilityExecutable,
the equivalent is to pipe the required text to it. You can create the desired text using echo statements in a for-loop, and pipe the entire loop output to utilityExecutable:
#!/bin/sh
list="OBJECT1 OBJECT2 OBJECT3"
for i in $list; do
echo "utilityCommand $i"
done | utilityExecutable
Yes, this is tricky and can be confusing! You have to modify your codes as follow.
#!/bin/sh
list="OBJECT1 OBJECT2 OBJECT3"
utilityExecutable << EOF
list="$list"
for i in \$list ; do
utilityCommand \$i
done
EOF
This is because heredoc uses its own variables, which are completely separate from the shell. When you are inside heredoc, you have to use and modify heredoc's own variables. So the \$ is needed to reference heredoc's own variables instead of shell variables when inside heredoc.
cat << EOF
$(
for i in {1..10}; do
echo $i;
done
)
EOF
commandxyz -noenv<<EOF
echo "INFO - Inside eof"
t_files=("${p_files[#]}")
#copy array
#echo \${t_files[*]}
#all elements from array
#echo \${#t_files[#]}
#array length
for i in \${t_files[#]} ; do
echo -e \$i;
do other stuff \$i;
done
cat $patch_file
git apply $patch_file
EOF
myVar=$(
for i in {1..5}; do
echo hello;
echo world;
done;
); cat <<< $myVar
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.
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
I've a .txt file which contains
abc.com
google.com
....
....
yahoo.com
And I'm interested in loading it to a bash script as a list (i.e. Domain_List=( "abc.com" "google.com" .... "yahoo.com") ). Is it possible to do?
Additional information, once the list is obtained it is used in a for loop and if statements.
for i in "${Domain_list[#]}
do
if grep -q "${Domain_list[counter]}" domains.log
....
....
fi
....
let counter=counter+1
done
Thank you,
Update:
I've changed the format to Domain_list=( "google.com .... "yahoo.com" ), and using source Doamin.txt allows me to use Domain_list as a list in the bash script.
#!/bin/bash
counter=0
source domain.txt
for i in "${domain_list[#]}"
do
echo "${domain_list[counter]}"
let counter=counter+1
done
echo "$counter"
Suppose, your datafile name is web.txt. Using command substitution (backtics) and cat, the array can be built. Pl. see the following code,
myarray=(`cat web.txt`)
noofelements=${#myarray[*]}
#now traverse the array
counter=0
while [ $counter -lt $noofelements ]
do
echo " Element $counter is ${myarray[$counter]}"
counter=$(( $counter + 1 ))
done
Domain_list=()
while read addr
do
Domain_list+=($addr)
done < addresses.txt
That should store each line of the text file into the array.
I used the source command, and it works fine.
#!/bin/bash
counter=0
source domain.txt
for i in "${domain_list[#]}"
do
echo "${domain_list[counter]}"
let counter=counter+1
done
echo "$counter"
There's no need for a counter if we're sourcing the list from a file. You can simply iterate through the list and echo the value.
#!/bin/bash
source domain.txt
for i in ${domain_list[#]}
do
echo $i
done
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?