Ruby string containing ${...} - ruby

In the Ruby string :
"${0} ${1} ${2:hello}"
is ${i} the ith argument in the command that called this particular file.
Tried searching the web for "Ruby ${0}" however the search engines don't like non-alphanumeric characters.
Consulted a Ruby book which says #{...} will substitute the results of the code in the braces, however this does not mention ${...}, is this a special syntax to substitute argvalues into a string, thanks very much,
Joel

As mentioned above ${0} will do nothing special, $0 gives the name of the script, $1 gives the first match from a regular expression.
To interpolate a command line argument you'd normally do this:
puts "first argument = #{ARGV[0]}"
However, ARGV is also aliased as $* so you could also write
puts "first argument = #{$*[0]}"
Perhaps that's where the confusion arose?

Related

What does "unterminated quoted string meets end of file" mean in MacVim?

I'm looking a way to compile Ruby code on OSX. I am using MacVim, and my code says:
puts "test"
I type rubydo %, and I get an error message SyntaxError: eval:1: unterminated quoted string meets end of file. What am I doing wrong?
Vim's rubydo command executes a command. You may have thought it was a filename (and used "%" as the parameter, i.e., the current buffer). The % is ruby's alternate string delimiter, and depending on how rubydo is implemented, the bare "%" could be mistaken for the beginning of a string.
The % Notation (Ruby Programming)
Vim documentation: if_ruby

How do you take a suffix of a string in bash using negative offsets?

I am trying to take the suffix of a string in Bash using the ${string:pos} substring syntax, but I cannot figure out why it won't work. I have managed to simplify my example code to this:
STRING="hello world"
POS=4
echo ${STRING:POS} # prints "o world"
echo ${STRING:4} # prints "o world"
POS=-4
echo ${STRING:POS} # prints "orld"
echo ${STRING:-4} # prints "hello world"
The first three lines work exactly as I would expect, but why does the final line print "hello world" instead of "orld"?
Because :- is parameter expansion syntax to "Use default values".
From the documentation:
When not performing substring expansion, using the form described
below (e.g., ‘:-’), Bash tests for a parameter that is unset or
null.
So by doing ${STRING:-4} you are actually asking bash to expand
STRING and if it is unset (have never been assigned before) or null
(a null string, printed as '') it will substitute the expansion with
4. In your example, STRING is set and thus it is expanded to its value.
As another answer states, you need to scape the expression to not
trigger the default value behavior, the manual specifies it:
Note that a negative offset must be separated from the colon by at
least one space to avoid being confused with the :- expansion.
For example:
${STRING:(-4)}
${STRING: -4}
You need to "escape" parameters starting with dash with a parenthesis or a space, otherwise bash will treat it as a normal string:
echo ${STRING:(-4)}
echo ${STRING: -4}

What does this variable assignment do?

I'm having to code a subversion hook script, and I found a few examples online, mostly python and perl. I found one or two shell scripts (bash) as well. I am confused by a line and am sorry this is so basic a question.
FILTER=".(sh|SH|exe|EXE|bat|BAT)$"
The script later uses this to perform a test, such as (assume EXT=ex):
if [[ "$FILTER" == *"$EXT"* ]]; then blah
My problem is the above test is true. However, I'm not asking you to assist in writing the script, just explaining the initial assignment of FILTER. I don't understand that line.
Editing in a closer example FILTER line. Of course the script, as written does not work, because 'ex' returns true, and not just 'exe'. My problem here is only, however, that I don't understant the layout of the variable assignment itself.
Why is there a period at the beginning? ".(sh..."
Why is there a dollar sign at the end? "...BAT)$"
Why are there pipes between each pattern? "sh|SH|exe"
You probably looking for something as next:
FILTER="\.(sh|SH|exe|EXE|bat|BAT)$"
for EXT
do
if [[ "$EXT" =~ $FILTER ]];
then
echo $EXT extension disallowed
else
echo $EXT is allowed
fi
done
save it to myscript.sh and run it as
myscript.sh bash ba.sh
and will get
bash is allowed
ba.sh extension disallowed
If you don't escape the "dot", e.g. with the FILTER=".(sh|SH|exe|EXE|bat|BAT)$" you will get
bash extension disallowed
ba.sh extension disallowed
What is (of course) wrong.
For the questions:
Why is there a period at the beginning? ".(sh..."
Because you want match .sh (as extension) and not for example bash (without the dot). And therefore the . must be escaped, like \. because the . in regex mean "any character.
Why is there a dollar sign at the end? "...BAT)$"
The $ mean = end of string. You want match file.sh and not file.sh.jpg. The .sh should be at the end of string.
Why are there pipes between each pattern? "sh|SH|exe"
In the rexex, the (...|...|...) construction delimites the "alternatives". As you sure quessed.
You really need read some "regex tutorial" - it is more complicated - and can't be explained in one answer.
Ps: NEVER use UPPERCASE variable names, they can collide with environment variables.
This just assigns a string to FILTER; the contents of that string have no special meaning. When you try to match it against the pattern *ex*, the result is true assuming that the value of $FILTER consists the string ex surrounded by anything on either side. This is true; ex is a substring of exe.
FILTER=".(sh|SH|exe|EXE|bat|BAT)$"
^^
|
+---- here is the "ex" from the pattern.
As I can this is similar to regular expression pattern:
In regular expressions the string start with can be show with ^, similarly in this case . represent seems doing that.
In the bracket you have exact string, which represents what the exact file extensions would be matched, they are 'Or' by using the '|'.
And at the end the expression should only pick the string will '$' or end point and not more than.
I would say that way original author might have looked at it and implemented it.

Convert Hex STDIN / ARGV / gets to ASCII in ruby

my Question is how I can convert the STDIN of cmd ARGV or gets from hex to ascii
I know that if I assigned hex string to variable it'll be converted once I print it
ex
hex_var = "\x41\41\x41\41"
puts hex_var
The result will be
AAAA
but I need to get the value from command line by (ARGV or gets)
say I've this lines
s = ARGV
puts s
# another idea
puts s[0].gsub('x' , '\x')
then I ran
ruby gett.rb \x41\x41\x41\x41
I got
\x41\x41\x41\x41
is there a way to get it work ?
There are a couple problems you're dealing with here. The first you've already tried to address, but I don't think your solution is really ideal. The backslashes you're passing in with the command line argument are being evaluated by the shell, and are never making it to the ruby script. If you're going to simply do a gsub in the script, there's no reason to even pass them in. And doing it your way means any 'x' in the arguments will get swapped out, even those that aren't being used to indicate a hex. It would be better to double escape the \ in the argument if possible. Without context of where the values are coming from, it's hard to say with way would actually be better.
ruby gett.rb \\x41\\x41
That way ARGV will actually get '\x41\x41', which is closer to what you want.
It's still not exactly what you want, though, because ARGV arguments are created without expression substitution (as though they are in single quotes). So Ruby is escaping that \ even though you don't want it to. Essentially you need to take that and re-evaluate it as though it were in double quotes.
eval('"%s"' % s)
where s is the string.
So to put it all together, you could end up with either of these:
# ruby gett.rb \x41\x41
ARGV.each do |s|
s = s.gsub('x' , '\x')
p eval('"%s"' % s)
end
# => "AA"
# ruby gett.rb \\x41\\x41
ARGV.each do |s|
p eval('"%s"' % s)
end
# => "AA"
Backlashes entered in the console will be interpreted by the shell and will
not make it into your Ruby script, unless you enter two backlashes in a row,
in which case you script will get a literal backlash and no automatic
conversion of hexadecimal character codes following those backlashes.
You can convert these escaped codes to characters manually if you replace the last line of your script with this:
puts s.gsub(/\\x([[:xdigit:]]{1,2})/) { $1.hex.chr }
Then run it with double backlashed input:
$ ruby gett.rb \\x41\\x42\\x43
ABC
When fetching user input through gets or similar, only a single backslash will be need to be entered by the user for each character escape, since that will indeed be passed to your script as literal backslashes and thus handled correctly by the above gsub call.
An alternative way when parsing command line arguments would be to let the shell interpret the character escapes for you. How to do this will depend on what shell you are using. If using bash, it can be done
like this:
$ echo $'\x41\x42\x43'
ABC
$ ruby -e 'puts ARGV' $'\x41\x42\x43'
ABC

Why does question mark get interpreted as "z" in Ruby

Why does this line output "z" instead of "?"
$ ruby -e 'puts %x[ echo #{"?"} ]'
Suppose the expression inside the #{...} is a variable that may have the value of "?". How should I modify this script so that the question mark is outputted instead of "z"?
(Please forgive the title of this question -- I don't yet understand what is going on here well enough to provide a more descriptive title.)
It's not ruby, it's your shell.
Many shells expand the ? character to match a single character in command line arguments.
It's useful, if you have a bunch of files name tempA,temp1,tempB,...,temp9 that you want to delete, but you don't want to delete 'temple'
% rm temp?
So I'm guessing you have a file or directory in your working directory named 'z', and the ? matches that, so it gets replaced by the shell.
Normally, when inside single quotes (like your ruby script) it wouldn't get expanded, but since you're passing the question mark to a shell command, it gets expanded there.
% ruby -e 'puts %x[ echo ? ]'
z
%
Should show you the same behaviour.
Also, if you touch a couple other single character filenames like a b c d, those should show up too:
% touch a b c
% ruby -e 'puts %x[ echo ? ]'
a b c z
%
If you want to avoid this when calling exterior shell commands from within ruby, you'll have to escape any strings you pass out. For most purposes String#inspect should give a good enough escaping.
It doesn't?
irb(main):001:0> puts %x[echo #{"?"}]
?
=> nil
Using #{} will give you the value of any variables inside - I'm not sure why you're using it instead of
puts %x[echo "?"]
or just
puts '?'

Resources