I came across a script with some code like this:
arr=($p)
np=${#arr[*]}
p is a string of integer pairs: "0,1 2,4 3,5" etc. First of all, I'm not 100% sure what the () do in the first line, but I think it just turns the things into an associative array of sorts? That may not be correct either .... But more than that, I'm at a complete loss as to what the second line does.
The parentheses in the first turn the result into an array, and it will be assigned indexes starting from 0 and split according to IFS (which by default includes whitespace). The ${#arr[*]}} gives the number of elements in the array.
Related
So I'm trying to figure out what a question from an old exam means and I'm slightly confused about one or two parts.
#!/bin/bash
awk '{$0 = tolower($0)
gsub(/[,.?;:#!\(\)]/),"",$0)
for(a=1;a<=NF;a++)
b[$a]++}
END print b[a],a}'
sort -sk2
Here is my interpretation:
target the bash script location
scan file with awk
convert string to lower case
sub all occurrences of symbols with nothing (ie. remove) and overwrite string
(here is my issue) for every field increment a by 1?
(again not sure what this is doing) b takes a's number and increments by 1?
end the for loop and print (b, a)
sort by size of the second field
I think the last four lines are my main issue. Also is it just me or is there an extra } in that question?
Thanks in advance.
The for loop is weirdly formatted. Here it is again with proper indentation:
for(a=1; a<=NF; a++)
b[$a]++
In other words, we loop over the field positions; for each, the count in the associative array b is incremented. So if the current input line is
foo bar poo bar baz
the script will do
b["foo"]++ # a is 1; $a is $1
b["bar"]++
b["poo"]++
b["bar"]++
b["baz"]++
So now b contains a set of tokens as keys, and the number of times each occurred as their respective values. In other words, this collects word counts for each word in the input.
The case folding and removal of punctuation normalizes the input so that
Word word word, word!
will count as four occurrences of "word", rather than one each for the capitalized version, the undecorated normal form, and the ones with punctuation attached at the end. It slightly distorts e.g. words which should properly be capitalized, and conflates into homographs words which are differentiated only by capitalization (such as china porcelain vs China the country.)
The END block is executed only when all input lines have been consumed, and thus b is fully loaded with all input words from all input lines, with their final counts. (Though here, there is no valid END block actually, because the opening brace after END is missing; this is a fatal syntax error. There isn't one closing brace too many, there's one non-optional opening brace missing.)
I need a regular expression that can be used to find the Nth entry in a comma-separated list.
For example, say this list looks like this:
abc,def,4322,mail#mailinator.com,3321,alpha-beta,43
...and I wanted to find the value of the 7th entry (alpha-beta).
My first thought would not be to use a regular expression, but to use something that splits the string into an array on the comma, but since you asked for a regex.
most regexes allow you to specify a minimum or maximum match, so something like this would probably work.
/(?:[^\,]*,){5}([^,]*)/
This is intended to match any number of character that are not a comma followed by a comma six times exactly (?:[^,]*,){5} - the ?: says to not capture - and then to match and capture any number of characters that are not a comma ([^,]+). You want to use the first capture group.
Let me know if you need more info.
EDIT: I edited the above to not capture the first part of the string. This regex works in C# and Ruby.
You could use something like:
([^,]*,){$m}([^,]*),
As a starting point. (Replace $m with the value of (n-1).) The content would be in capture group 2. This doesn't handle things like lists of size n, but that's just a matter of making the appropriate modifications for your situation.
#list = split /,/ => $string;
$it = $list[6];
or just
$it = (split /,/ => $string)[6];
Beats writing a pattern with a {6} in it every time.
I'm looking for a way to sort in selected block in Vim. The scenario is I have something like this
{:a
:c
:b}
# after sort, it should be
{:a
:b
:c}
How I do it now is I have to enter :a and :c to new lines, running sort on selected block and then put the brackets back later. I'm looking for a way to sort without doing this extra operation.
The following will reduce your effort slightly but still doesn't resolve it completely, basically it will sort based on what comes after the colon, then remove the brackets but it doesn't insert them again for you:
:'<,'>sort /^.\{-}:/ |%s/{\|}//g
Hope it helps, happy vimming.
One way you can do this is by reading the inner of the braces into a register.
"ayi{
This will copy the content, the lines, without the braces around them.
Then you can run that into the sort function
sort(split(getreg('a')))
This requires the modifiable flag to be set, as you're changing a non visible buffer. It sorts the buffer a in place. You could then paste that inside the braces vi{"ap.
Obviously you should put the while thing in a function/macro or command.
Here's one way with Ex commands. Sorting of ranges is pretty easy with :global and :sort. The following command sorts the lines between those delimited by curly braces:
:g/^{/+1,/^}/-1sort
But the complication here is that (in your example), the enclosing braces are on the same (first, last) lines as the data. We need to separate them out to adjacent lines first, and later undo that. :substitute can do that:
:%s/{\zs\|\ze}/\r/g
:g/^{/+1,/^}/-1sort
:%s/{\zs\n\|\n\ze}//g
I would like to implement a small subset of siri/cortana like features in command line.
For e.g.
$ What is the sum of 100 and 1000
> Response: 1100
$ What is the product of 10 and 12
> Response: 120
The questions are predefined regular expressions. It needs to call the matching function in ruby.
Pattern: What is the sum of (\d)+ and (\d)+
Ruby method to call: sum(a,b)
Any pointers/suggestion is appreciated.
That sounds exactly like cucumber, maybe take a look and see if you can just use their classes to hack something together :) ?
You could do something like the following:
question = gets.chomp
/\A.*(sum |product |quotient |difference )\D+([0-9]+)\D+([0-9]+).*\z/.match question
send($1, $2.to_i, $3.to_i)
Quick explanation for anyone that may be new to matching in Ruby:
This gets a line of input from the command line and scans it for a function name (i.e. sum, product, etc) followed by a space and potentially some non-digit characters. Then, it looks for a first number (similarly followed by a space and 0 or more non-digit characters) and a second number followed by nothing or anything. The parentheses determine what gets assigned to the variables preceded by a $, i.e. the substring that matches the contents of the first set of parentheses gets assigned to $1.
Next, it calls the method whose name is the value of $1 with the arguments (casted to integers) found in $2 and $3.
Obviously, this isn't generalized at all--you're putting the method names in the regex, and it's taking a fixed number of arguments--but it'll hopefully be useful for getting you on the right track.
I'm getting a string of few lines from the shell. Is it possible to get an Array with each line being its element?
Sure, depending on the output you could just split it. For example:
lines = `ls`.split
This solution is independent of the method you're using to execute the program. As long as you get the complete string you can split it.
The original question was splitting on lines, and the split function, by default, splits on white space. While that may be sufficient, you may want to pass in a regular expression, as in:
`ls -l`.split(/$/)
Which returns each line in a separate element in the array. However, it doesn't get rid of the initial carriage return or line feed. For that, you will want to use the map function to iterate over the array and apply strip to each, as in:
`ls -l`.split(/$/).map(&:strip)