How do i achieve "read -i" in a different way? - bash

I Have been looking on the internet but without finding a solution (hard to know what to serach for). I want a way to show "current value" on an input. Similar to what read -e -p "something: " -i "this" $variable does but in Busybox sh. As that option only became available in Bash4 which is not default. I will have to solve it another way. Not sure if this is possible..
read -p "Select by entering an number: " ANS
case $ANS in
1 ) ANS="%R | %a %d %b" ;;
2 ) ANS="%R, %a %d %b" ;;
3 ) read -p "Enter a custom string (ex. %R): " ANS ;;
4 ) ANS="%R" ;;
* ) read -p "Just answer with a number between 1 to 4. Aborting!" end; exit 0 ;;
esac
What i want is that case #3 will show the current value of the file. Ex. If the file has %R as current value. Then that is what i want it to show on input for user to interactively change it.

Until you can give us examples of what you want the programme to take as an 'input' and then give as an 'output', I suggest you read TLPD's section on 'read'

Related

Create if statement to iterate over a list of names and create name if not in list?

I am working with an Azure shared image gallery and trying to write a bash if statement to iterate through the list of image definition names and if that image definition name is not there, create it elif, etc...
I have a variable set as:
defs=$(az sig image-definition list --resource-group $MyRG --gallery-name $mySIG --query [*].name) \
echo "$defs"
What I'm attempting to do is create an if statement that will iterate through this list of image definition names in my Azure compute gallery, and create a specified name if it does not exist.
My original assumption was something like if [$defs != x but not sure how to go about setting x, as it would be a user input for someone wanting to create a new definition.
Sorry if my question is unclear.
If there's more info I can provide please let me know.
The problem I'm facing is that I understand bash somewhat but not in conjunction with how exactly I am attempting to apply it to my Azure image definitions issue.
You can use read to ask a user for input.
$ read -p "please enter a definition: " x
please enter a definition: def4
$ echo $x
def4
Then, assuming $defs is a space separated list of definitions, could do something like this:
# list of defs..
defs="def1 def2 def3"
# ask user to enter a definition
read -p "please enter a definition: " x
# set this to false until def is found
def_exists=false
# iterate over list of defs and see if user value is found
for i in ${defs}; do
echo $i
if [[ ${i} == "${x}" ]]; then
echo "found it"
def_exists=true
fi
done
# if user def exists, good
if $def_exists; then
echo "definition exists already.. nothing to do"
# otherwise...
else
# do something
echo "$x not found.. do stuff.."
fi
Example where def is in existing list:
please enter a definition: def1
def1
found it
def2
def3
definition exists already.. nothing to do
Example where def is not in existing list:
please enter a definition: def4
def1
def2
def3
def4 not found.. do stuff..
This is what my defs variable holds, and what the commenter above was asking you to provide so we can see what type of data is being referenced.
$ typeset -p defs
declare -- defs="def1 def2 def3"
If the data/ definitions have spaces, etc.. could use arrays or we can look at other options. If you post some examples of the definitions, like are they a single word? multiple words with spaces in them, etc. Hope this helps!
You can use Global Parameters --query and --output to query the list from the output of az sig image-version list in Azure CLI. Please refer to :az sig image-definition
For example:
defs=$(az sig image-definition list --resource-group Wicresoft-Support --gallery-name douGallery --query [*].name --output tsv)
And then use typeset -p defs to see the exact contents of the variable. It’s a string structure from the below picture.
For example, here is bash script with Azure CLI
# convert to array
defs_array=($defs)
#declare -p defs_array
# the length of array
length=${#defs_array[#]}
read -p "please enter a name: " x
for i in ${defs_array[#]}
do
if [[ ${i} == $x ]]; then
echo "found"
break
else
if [[ ${i} == ${defs_array[-1]} ]];then
echo "not found"
fi
fi
done

Ksh - Script: List Files and store as variable

I'm using kshon an HP-UX box.
In a portion of my script, I want to list certain files (*.xml), have them numbered and have the user choose a file by typing the number and hitting enter. That filename will then be stored as a variable.
Example of output:
Please choose a file:
1) bar27.xml
2) foo1.xml
3) foobar4.xml
Then the user types in 1, 2, or 3 and hit enter. The file name chosen needs to be stored as a variable. So if the user chooses 2 the variable should contain foo1.xml.
I've come up with the following which works:
files=$(ls *.xml)
i=1
for j in $files
do
echo "$i) $j"
file[i]=$j
i=$(( i + 1 ))
done
echo "Choose an XML file from above to use:"
read v_CHOOSELIST
echo "File chosen: ${file[$v_CHOOSELIST]}"

./test: line 22: syntax error near unexpected token `done'

#!/bin/bash
# script to create new instance by taking inputs from user
source /root/keystonerc_admin
unset http_proxy
function main {
echo "Please choose:
1. Create instance from an image
2. Create instance from a volume
3. Exit"
While true do
read SELECT
case "$SELECT" in
1) SELECT=func_create_from_image;;
2) SELECT=func_create_from_volume;;
3) SELECT=exit;;
*) echo Invalid selection.; continue
esac
break
done
}
function func_create_from_image {
echo "List of flavors"
nova flavor-list
echo "Enter flavor id from the list"
read flavor_id
echo "List of images"
nova image-list
echo "Enter image id from the list"
read image_id
echo "List of security groups"
nova secgroup-list --all-tenants
echo "Enter security group name from the list"
read secgroup_name
echo "List of keypairs"
nova keypair-list
echo "Enter keypair name from the list"
read keypair_id
echo "Enter display name of instance"
read display_name
## use "set" for debugging
##set -x
nova boot --display $display_name --flavor $flavor_id --image $image_id \
--key_name $keypair_id --security_group $secgroup_name
##set +x
}
function func_create_from_volume {
echo "Please choose:
1. Use existing bootable volume
2. Create new bootable volume
3. Exit"
while true do
read SELECT
case "$SELECT" in
1) SELECT=create_instance_from__existing_volume;;
2) SELECT=create_instance_from_new_volume;;
3) SELECT=exit;;
*) echo Invalid selection.; continue
esac
break
done
}
create_instance_from_new_volume {
echo "Specify image id from the below list"
nova image-list
read image_id
echo "specify size in GB, only specify number"
read vol_size
echo "Specify image name to be displayed in cinder list"
read vol_disp_name
set -x
cinder create --image-id $image_id --display-name $vol_disp_name $vol_size
set +x
echo "volume created"
cinder list
echo "create instance"
create_instance_from__existing_volume
}
create_instance_from_existing_volume {
echo "Specify volume id from the below list"
cinder list
read vol_id
echo "Pick flavor id from the below list"
nova flavor-list
read flavor_id
echo "specify size in GB, only specify number or leave blank for system to decide"
read vol_size
echo "Specify type of volume either snap or other or leave blank if not known"
read vol_type
echo "Specify 1 if volume should be deleted when the instance terminates or specify 2 if volume remains after
instance terminates"
read vol_del
if [$vol_del!=0 or $vol_del!=1] then
echo "Specify either 1 or 0"
fi
echo "Specify display name for instance"
read inst_disp_name
echo "Creating instance"
nova boot --flavor $flavor_id --block_device_mapping vda=$vol_id:$vol_type:$vol_size:$vol_del $inst_disp_name
}
While true do
Bash is case-sensitive - you need while rather than While. And you also need to either move the do to the next line or put a semicolon before it
while true; do
Also your if condition further down is suspect:
if [$vol_del!=0 or $vol_del!=1] then
Aside from the syntax errors, this condition will always be true (since if the value is 1 then it is not 0 and vice versa). I suspect you wanted and rather than or:
if [ $vol_del != 0 -a $vol_del != 1 ]; then
Use
while true; do
instead of
While true do
because do isn't an argument to true command
In theory, do should be on a separate line:
while ....
do
....
done
Same with then:
if .....
then
.....
fi
However, people like putting them on the same line in the K&R Style. To do that, you need a semicolon to show the shell when the while line ends, so the do is on a different line:
while ....; do
....
done
This may no longer be necessary in newer versions of BASH, but it should be done. I prefer using an extra line just because the shell prefers it.
The other problem and the actual problem has to do with the While on line #13 as While (uppercase W and not lowercase w).
Two thing will help catch this in the future:
Use set -xv to turn on debugging and set +xv to turn off debugging. In this case, you'll see the error happens when you enter the while loop when Line #13 gets executed. You can set export PS4=\$LINENO+ to show line numbers when this debugging is on. To turn off debugging, you set +xv.
Use a program editor that has syntax highlighting. I saw this immediately because the While wasn't in the correct color. I took a closer look and saw the capitalized While.

How to print and edit variable content at the same place on runtime of a Unix shell script?

I have been looking all around (with no avail) to perform the following:
I want to display and able to edit if necessary the content of a variable in runtime for a Unix shell script after giving it a value. The idea goes like this:
Suppose we have a variable value either defined in script or by user input
var=12345
Print the variable value, but also leave the cursor in that position of printing and either press just enter to leave it intact or enter a new value in runtime
Edit variable content (press Enter to leave intact) : 12345
at this point at runtime, I want to leave the cursor in the position of number 1, while showing the variable, and working in the way that if I press Enter, leave the original content (12345) or read for a new value in that same place and modify. Clearing the display of the variable when typing anything else than Enter would be a big plus.
I have looked all around for a way to do this, but just haven't found anything. Anyone willing to provide a solution?
I would suggest you doing this in another way:
var=12345
echo "Change the value of Var (current value: $var)"
read -p "New value (Press Enter to skip):" nvar
if [[ "$nvar" != "" ]]; then
var="$nvar"
fi
echo $var
with this, it will prompt:
Change the value of Var (current value: 12345)
New value (Press Enter to skip):
what you wanted in the question (without the "big plus" part), could be achieved too:
var=12345
echo -ne "Now you may want to change the value: \n$var\r"
read nvar
if [[ "$nvar" != "" ]]; then
var="$nvar"
fi
echo $var
with this, it will prompt (cursor sits between ** )
Now you may want to change the value:
*1*2345
With bash, you could use the readline option for read, but that does not put the cursor at the beginning. It does however do what you want
var=12345
read -ep "Enter new value: " -i $var var
If you need the cursor to go back, you can do this:
var=12345
prompt="Enter new value: $var"
for ((i=1; i<=${#var}; i++)); do prompt+=$'\b'; done
read -p "$prompt" new
[[ -z $new ]] && new=$var

Bash user prompt while reading file

I am trying to create a user prompt while reading a file a line by line in Bash. The idea is for me to plot various files one-by-one using Gnuplot. Here is what I have:
#!/bin/bash
echo "Enter filename that contains the filenames:"
read fname
xr="[1e8:1e20]"
yr="[1:1e13]"
while read line
do
echo -e "reset\nset log\nset xrange$xr\nset yrange$yr\nset xlabel \"Frequency [Hz]\"\nset ylabel \"F_{/Symbol n} [Jy Hz]\"\nset key top left\nplot \"$line.dat\" u 3:(\$3*\$4)*1e26 w l ti \"$line^o\" \n"> plt.gp
gnuplot plt.gp
done < $fname
I would like to enter a user input/"continue?" type thing before "gnuplot plt.gp" command, because at the moment it just plots everything rapidly and then exits. The standard read -p command does not work here. I read somewhere I may need to use file descriptor exec 5 command, but I don't understand. Thanks.
#!/bin/bash
read -p 'Enter filename that contains the filenames: ' fname
xr="[1e8:1e20]"
yr="[1:1e13]"
while read line
do
echo -e "reset\nset log\nset xrange$xr\nset yrange$yr\nset xlabel \"Frequency [Hz]\"\nset ylabel \"F_{/Symbol n} [Jy Hz]\"\nset key top left\nplot \"$line.dat\" u 3:(\$3*\$4)*1e26 w l ti \"$line^o\" \n"> plt.gp
gnuplot plt.gp
read -p 'Do you want to continue? [Y/n]: ' want_to_continue </dev/tty
case "${want_to_continue}" in
Y|y)
continue
;;
*)
echo "OK. Bye!"
break
;;
esac
done < ${fname}

Resources