Creating multiple variables in Pharo gives me a "variable or expression expected" error - smalltalk

I'm confused about why this code seems to work fine in isolation, but I get an error when I put it all together.
The following snippet prints 'Hello World!' when printed:
| blah |
blah := 'Hello '.
blah, 'World!'.
But the following code block gives me the error Variable or expression expected
| blah |
blah := 'Hello '.
blah, 'World!'.
| blah2 |
blah2 := 'World!'.
blah, blah2.
Could someone explain what's going on here?

variable declarations are only allowed at the beginning of a block or method:
| blah blah2 |
blah := 'Hello '.
blah, 'World!'.
blah2 := 'World!'.
blah, blah2.

Related

How to split a text file at lines which begin with a number

I have a file ('tosplit') that looks like this:
20210101 blah blah
blah 20210101
blah 20210101
blah 20210101
20210315 blah blah
blah 20210315
blah 20210315
blah 20210315
I would like to split this file into two files that look like this (i.e., each file contains the line starting with the date and all of the lines that follow and start with 'blah'):
(file 1)
20210101 blah blah
blah 20210101
blah 20210101
blah 20210101
(file 2)
20210315 blah blah
blah 20210315
blah 20210315
blah 20210315
Using csplit (>csplit -z tosplit /2021/ '{*}'), doesn't work, as the delimiter occurs multiple times in the block I am trying to preserve as a single file. Is there a way to split based on the first character of the line being a number and not a letter? Many thanks in advance.
Given:
cat tosplit
20210101 blah blah
blah 20210101
blah 20210101
blah 20210101
20210315 blah blah
blah 20210315
blah 20210315
blah 20210315
2021 blah
blah
You can use csplit by adding an anchor ^ to specify only to use 2021 at the start of the line:
csplit -z tosplit /^2021/ '{*}'
61
61
15
Which creates the files:
xx00:
20210101 blah blah
blah 20210101
blah 20210101
blah 20210101
xx01:
20210315 blah blah
blah 20210315
blah 20210315
blah 20210315
xx02:
2021 blah
blah
Try it online
You can try this awk if the condition is always 2021.
It generates files (and overwrites existing ones without asking) with names fileX with X being the number of splits.
$ awk 'BEGIN{x=1} NR>1 && /^2021/{ close("file"x); x++ }
{ print > ("file"x) }' tosplit
$ for i in file[12];do echo $i; cat $i ;done
file1
20210101 blah blah
blah 20210101
blah 20210101
blah 20210101
file2
20210315 blah blah
blah 20210315
blah 20210315
blah 20210315
A more generalized version
$ awk 'BEGIN{x=1} NR>1 && /^[[:digit:]]/{ close("file"x); x++ }
{ print > ("file"x) }'

How to avoid leading space using cut command?

Requirement: I need to use only grep/cut/join.
I have data like:
3 abcd
23 xyz
1234 abc
I want to pipe this data to cut and then extract columns. But, when I am using cut -d' ' -f 1,2 it treats each space as its own column divider. I would prefer the first two rows be trimmed prior to cut. Is there a way?
Example (I have used tr for demonstration purposes of where the spaces are here; it is not allowed in the solution):
$ echo ' 3 abcd
23 xyz
1234 abc' | cut -d' ' -f 1,2 | tr ' ' '_'
_
_23
1234_abc
Expected output:
$3 abcd
23 xyz
1234 abc
Using just grep, you can accomplish this with the following pipe:
grep -oe "[^ ][^ ]* *[^ ][^ ]*$"
grep # a tool for matching text
-o # only prints out matching text
-e # uses a regex
[^ ] # match anything that isn't a space
* # match zero or more of the previous element
$ # the end of the line
Note: This does not account for trailing whitespace.
Demonstration:
$ echo ' 3 abcd
23 xyz
1234 abc' | grep -oe "[^ ][^ ]* *[^ ][^ ]*$"
3 abcd
23 xyz
1234 abc

Grammar for given language

I am given the language {w ∈ {a,b}∗| |w|a = |w|b + 1}. and am asked to find a grammar.
I have come up with the following:
S->aSb | bSa | aAa | bBb | a
A->bS
B->?
and was wondering if this was correct, or if not why?
It's not correct, because it cannot generate the valid sentence:
baaab
which has one more a than b. It should be obvious that this sentence cannot be generated because every sentence generated by your language has different start and end characters.
Edit The edited question is also not correct because the productions:
S -> ... | aAa | a | ...
A -> bS
is equivalent to (by substituting the RHS of A for its use in S):
S -> ... | abSa | a | ...
which will match as follows:
S -> abSa -> abaa

Awk: Var types and output format

This is my super complex awk program:
#!/usr/bin/awk -f
BEGIN {
count = 0
}
{ if ( $1 == "r" )
{
nom = $2
ip= $7
numerolinea = NR
}
else {
where = match($0, "Fast")
if ( where )
{
count++
printf( "\t%5i %20s %15s\n",count,nom,ip )
}
}
}
So as you can see nom and ip are treated as strings each one with its own length. An excerpt of the output it'd be like this:
| 111 cutemyserver1 93.27.255.24 |
| 112 thisisthenamemyserver2 60.231.2.255 |
| 113 anotherlongmyserver3 191.44.192.260 |
| 114 myserver4 173.374.76.183 |
| 115 formyserver5 145.146.321.8 |
| 116 myserver6 64.31.359.70 |
| 117 foofoomyserver7 245.16.19.338 |
As you also can see, count is an integer. My goal is countto be aligned as nom and ip do are, because of this:
| 8 myserver6 91.580.144.231 |
| 9 narnd 163.11.783.10 |
| 10 erreer 59.194.0.353 |
| 11 111111 178.70.644.91 |
But cheating wih %5i doesn't work.
Thanks
I've fixed your problem and taken the liberty of making your code more "awk-like":
#!/usr/bin/awk -f
$1=="r" {nom=$2;ip=$7;next;}
/Fast/ {printf "\t%5d %20s %15s\n",++count,nom,ip;}
NB.
count doesn't require initialisation in this example.
numerolinea is unreferenced
condition {...} is a more "awk-like" way of saying if...then
next prevents the subsequent conditions being tested
++count updates the variable before offering its value
/Fast/ {...} executes when the regular-expression Fast is in $0
As Glenn correctly states, %5d is the syntax you require within your printf

How do I display a tree view based on this given database data?

The table looks like:
id | title | parent | depth |
---+-------+--------+-------+
1 | blah | 0 | 0
---+-------+--------+-------+
2 | blah | 0 | 0
---+-------+--------+-------+
3 | blah | 0 | 0
---+-------+--------+-------+
4 | blah | 2 | 1
---+-------+--------+-------+
5 | blah | 2 | 1
---+-------+--------+-------+
6 | blah | 5 | 2
---+-------+--------+-------+
I want to take that data and output it into a tree like view. Similar to:
1 - blah
2 - blah
4 - blah
5 - blah
6 - blah
3 - blah
Someone suggested I use the query:
SELECT title, depth FROM table ORDER BY parent, id
I could then use the depth to create the whitespace on the left and format the tree. This works up until I use HTML. I want to be able to format it nicely in valid HTML and then style it with CSS, etc...
Using just the depth, I can't think of a way to wrap the comments in a div class="parent/child" type structure.
How can I format the data?
Use a <ul> in HTML, with a <li> for each item. Every time you increase in depth compared to the last item, add one <ul> to the current <li> instead of closing it. If the current depth is lower than the previous, close off one </ul></li> pair for each level of depth difference.
if you already have figured out how to get the depth of an entry (or the number of ancestors that is), then you could try the following:
css code:
.tab {
margin-left: 20px;
}
rendered html code:
<p>
<span class="">1 - blah</span><br />
<span class="">2 - blah</span><br />
<span class="tab">4 - blah</span><br />
<span class="tab">5 - blah</span><br />
<span class="tab tab">6 - blah</span><br />
<span class="">3 - blah</span>
</p>
and you'll use your logic to determine how many "tab" to add to the span's class attribute. each "tab" you add puts that line 20 more pixels to the right.