Randomize the echo char in Highline's ask method? - ruby

I am trying to randomize the echo character in the Highline gem's ask method, but could not get it to work. Did I not do this right?
srand
ask("password: ") { |q| q.echo = ('a'.ord+rand(26)).chr }
The character is randomized for each ask() call, but not each character. The first run will echo the same character, i.e. 'cccc'. The next run will echo 'mmmm', etc.

echo is a variable value used to determine whether to echo output. From the highline source:
# [echo] Can be set to +true+ or +false+ to control whether or not input will
# be echoed back to the user. A setting of +true+ will cause echo to
# match input, but any other true value will be treated as a String to
# echo for each character typed.
Your code (('a'.ord+rand(26)).chr) is being evaluated once per ask, stored in the echo variable within highline, and then printed out for each character entered.
You can't get it to print a different random character per input character without modifying highline.

Related

Bash Variable Not Being Assigned

I have this bash script, that gets an input from the user, and returns a phonetic transcription of the word, even if no transcription is available. However, the variable results isn't being assigned as a blank line is being printed instead of the value inside.
I have tried putting the commands into a different script, and that also produced blank lines, and doubled checked that there was no space between results and =
Code:
#!/usr/bin/env bash
#check if user entered a word to translate to ipa
#if a word was not entered prompt the user to enter a word
#else set the word passed as an argument to the variable current
if [ -z "$1" ]
then
echo "You did not enter a word for translation, Please enter one now: "
read current
else
current=$1
fi
#confirm to user the word they entered
echo "The word you chose for translation: $current"
#format the word into '< w o r d >'
onmt_word=$(python ONMT_DATA_FORMAT.py "$current")
#write over current word in temp_word.txt
echo $onmt_word > temp_word.txt
#translate the word in temp_word.txt using openNMT with the model created from a set of 32k words
results=$(onmt_translate -gpu -1 -model eng_ipa_model1_steps/eng_ipa_model1_step_100000.pt -src temp_word.txt -replace_unk -verbose -output model1_step_10000_temp_pred)
#print only the results we care about, i.e. the translated IPA
echo "The provided IPA translation is:"
echo $results | egrep -o '< .* >'
echo "Please ignore the first and last symbol, these are needed for the translation process."
Source:
https://github.com/LonelyRider-cs/LING4100_project

How to in-line modify a variable in a shell script?

I have a shell script that sets a variable RESULT= as empty to begin with. Then, the script makes a curl get request if RESULT is empty (if [ -z $RESULT ];then...), and then prints it out, telling the user to set the empty variable.
I am wondering if there is a way for me to in-line modify the RESULT variable only if it is empty, so that afterwards, the variable instead reads a string, such as
RESULT="SUCCESS"
Simply use
: ${RESULT:=$(curl ...)
If RESULT is initially empty or unset, curl will run and its output assigned to RESULT. Otherwise, curl is not run, and RESULT retains whatever value it started with. (Note that RESULT may be an environment variable, with a value before the script actually starts.)
You can extend this to handle arguments as well.
# :-, not :=
RESULT=${1:-$(curl ...)}
curl only runs if the first argument is the empty string or not present:
yourScript
yourScript ""
Otherwise, it assigns whatever the first argument is to RESULT:
yourScript "$(curl ...)"
Supply an assigning default.
if [[ b0Gus == "${RESULT:=b0Gus}" ]]; then... # RESULT now b0Gus if it was empty
This returns the value of RESULT if it has one, else it sets it and returns that. Note that it is more like ((++x)) than ((x++)) in that it applies the change before returning the content to the test operator.
If you use a dash instead of equals, it returns the alternate value, but doesn't set the variable -
if [[ b0Gus == "${RESULT:-b0Gus}" ]]; then... # RESULT still empty after match
See https://www.gnu.org/software/bash/manual/html_node/Shell-Parameter-Expansion.html for more.
You can apply this by passing it as args to a no-op, too.
: ${RESULT:=b0Gus}
The : just returns true, but the parser still evaluates its arguments, which will set the var if empty - this is similar to a Perl ||= assignment, though that isn't inline.

Why am I getting a leading sing quote in this echo?

I am trying to debug a bash shell script where I am trying to surround a string/variable with single quotes. I am seeing the following results and am stumped on how to debug this. It obviously has something to do with the content of the variable. I thought the variable may be an array hence some of the echo statements. IN_JSON is being constructed via calls to "jq" to construct some JSON.
echo "IN_JSON = ${IN_JSON}"
echo "IN_JSON = ${IN_JSON[*]}"
echo "IN_JSON = '${IN_JSON[*]}'"
echo "IN_JSON = '" ${IN_JSON} "'"
echo "${#IN_JSON[#]}"
Output:
IN_JSON = {"name":"RX-CLAIM-FILLED"}
IN_JSON = {"name":"RX-CLAIM-FILLED"}
'N_JSON = '{"name":"RX-CLAIM-FILLED"}
'_JSON = ' {"name":"RX-CLAIM-FILLED"}
1
What's going on here and how do I troubleshoot this? It obviously has something to do with the contents of IN_JSON, but I'm not sure why or what is going on here.
The expansion of ${IN_JSON[*]} contains a carriage return character that resets the position of the cursor to beginning of the line, so that the next character ' is printed on beginning of the line.
Most probably, you want to run your file via dos2unix.

How to not print a scaped quote

I need echo a html string;
echo <html><body></body></html>;
result < it was unexpected
echo "<html><body></body></html>";
result "<html><body></body></html>";
I do not want the double quotation marks to be displayed;
echo ^<html^>^</html^>
result <html></html>
It works perfect for me, however the string is large, and if I give scape on all the characters, it will exceed the limit size of the prompt;
Note, I can not save this string to a file.
I think you can use SET command with quotation mark:
SET "string=<html><body></body></html>;"
then ECHO it goes ok

Bash Function is not getting called, unless I echo the return value

In my program I am trying to return a value from a function, the return value is string. Everything works fine(atleast some part), if I echo the value once it is returned, but it is not even calling the function, if I dont return.... Consider the code below....
#!/bin/bash
function get_last_name() {
echo "Get Last Name"
ipath=$1
IFS='/'
set $ipath
for item
do
last=$item
done
echo $last
}
main() {
path='/var/lib/iscsi/ifaces/iface0'
current=$(get_last_name "$path")
echo -n "Current="
echo $current
}
main
It gives me an output like this
OUTPUT
Current=Get Last Name iface0
If I comment the echo $current, then the I am not even seeing the "Get Last Name", which makes to come to conclusion, that it is not even calling the function. Please let me know what mistake I am making. But one thing I am sure, bash is the ugliest language I have ever seen.......
Functions do not have return values in bash. When you write
current=$(get_last_name "$path")
you are not assigning a return value to current. You are capturing the standard output of get_last_name (written using the echo command) and assigning it to current. That's why you don't see "Get last name"; that text does not make it to the terminal, but is stored in current.
Detailed explanation
Let's walk through get_last_name first (with some slight modifications to simplify the explanation):
function get_last_name () {
ipath=$1
local IFS='/'
set $ipath
for item
do
last=$item
done
echo "Get Last Name"
echo $last
}
I added the local command before IFS so that the change is confined to the body of get_last_name, and I moved the first echo to the end to emphasize the similarity between the two echo statements. When get_last_name is called, it processes its single argument (a string containing a file path), then echoes two strings: "Get Last Name" and the final component of the file path. If you were to run execute this function from the command line, it would appear something like this:
$ get_last_name /foo/bar/baz
Get Last Name
baz
The exit code of the function would be the exit code of the last command executed, in this case echo $last. This will be 0 as long as the write succeeds (which it almost certainly will).
Now, we look at the function main, which calls get_last_name:
main() {
path='/var/lib/iscsi/ifaces/iface0'
current=$(get_last_name "$path")
echo -n "Current="
echo $current
}
Just like with get_last_name, main will not have a return value; it will produce an exit code which is the exit code of echo $current. The function begins by calling get_last_name inside a command substitution ($(...)), which will capture all the standard output from get_last_name and treat it as a string.
DIGRESSION
Note the difference between the following:
current=$(get_last_name "$path")
sets the value of current to the accumulated standard output of get_last_name. (Among other things, newlines in the output are replaced with spaces, but the full explanation of how whitespace is handled is a topic for another day). This has nothing to do with return values; remember, the exit code (the closet thing bash has to "return values") is a single integer.
current=get_last_name "$path"
would not even call get_last_name. It would interpret "$path" as the name of a command and try to execute it. That command would have a variable current with the string value "get_last_name" in its environment.
The point being, get_last_name doesn't "return" anything that you can assign to a variable. It has an exit code, and it can write to standard output. The $(...) construct lets you capture that output as a string, which you can then (among other things) assign to a variable.
Back to main
Once the value of current is set to the output generated by get_last_name, we execute
two last echo statements to write to standard output again. The first writes "Current=" without a newline, so that the next echo statement produces text on the same line as the first. The second just echoes the value of current.
When you commented out the last echo of main, you didn't stop get_last_name from being executed (it had already been executed). Rather, you just didn't print the contents of the current variable, where the output of get_last_name was placed rather than on the terminal.

Resources