Here's an old school IF statement for you, but there is a problem - qbasic

I have an IF statement in QBASIC... yes... QBASIC...
I have been teaching someone to program (I decided this would be nice and easy to see
how the syntax works).
...Anyway, I have this code:
CLS
start:
INPUT ">>", a$
PRINT a$
IF (INSTR(a$, "do you")) THEN
IF (INSTR(a$, "like")) THEN
IF (INSTR(a$, "cheese")) THEN PRINT "Yep, I like cheese":
IF (INSTR(a$, "music")) THEN PRINT "Depends, which genre?": GOTO musicGenre
ELSE IF (INSTR(a$, "hate")) THEN
IF (INSTR(a$, "cheese")) THEN PRINT "No, I like cheese"
END IF
END IF
END IF
musicGenre:
INPUT ">>", m$
SELECT CASE (m$)
CASE "pop"
PRINT "..pop! lol, baa baa"
CASE "rock"
PRINT "Rock is ok"
END SELECT
GOTO start
But when I type "do you like cheese?" it seems to only reply "Yep, I like cheese" every other time...
Could anyone shed some light on this?
note:
"do you like music?" works every time...
note 2:
Screenshot of the output:

Your code you provided appears correct.
Try one of the following:
If possible, send us a larger code sample. I'm guessing the error is outside the code you provided.
Output the input (a$) before the first IF to confirm your code will be working with the expected input.
In most languages, FALSE is zero and true is anything else. However, you may want to be more explicit with the following IF (INSTR(a$) > 0).
EDIT: You should put a goto start on any cheese result. Otherwise, it's going to the musicGenre code.

CLS
start:
INPUT ">>", a$
IF (INSTR(1, a$, "do you")) THEN
IF (INSTR(1, a$, "like")) THEN
IF (INSTR(1, a$, "cheese")) THEN PRINT "Yep, I like cheese"
IF (INSTR(1, a$, "music")) THEN PRINT "Depends, which genre?": GOSUB musicGenre
END IF
IF (INSTR(1, a$, "hate")) THEN
IF (INSTR(1, a$, "cheese")) THEN PRINT "No, I like cheese"
END IF
END IF
GOTO start
musicGenre:
INPUT ">>", m$
SELECT CASE (m$)
CASE "pop"
PRINT "..pop! lol, baa baa"
CASE "rock"
PRINT "Rock is ok"
END SELECT
RETURN

This program demonstrates parsing input and gosubs in Basic.
REM Cheese progran source:
CLS
DO
INPUT ">>", a$
a$ = LCASE$(a$)
PRINT a$
IF INSTR(a$, "do you") THEN
IF INSTR(a$, "like") THEN
IF INSTR(a$, "cheese") THEN
PRINT "Yep, I like cheese":
END IF
IF INSTR(a$, "music") THEN
PRINT "Depends, which genre?"
GOSUB MusicGenre
END IF
ELSE
IF INSTR(a$, "hate") THEN
IF INSTR(a$, "cheese") THEN
PRINT "No, I like cheese"
END IF
END IF
END IF
END IF
LOOP
END
MusicGenre:
INPUT ">>>", m$
a$ = LCASE$(a$)
SELECT CASE (m$)
CASE "pop"
PRINT "..pop! lol, baa baa"
CASE "rock"
PRINT "Rock is ok"
END SELECT
RETURN

Related

awk perl grep pattern match ignoring

I have a file with about 100,000 lines that look more of less like this:
if (uri=~"^proto:[+]*55555.*"){
rewritehostport("10.10.10.2:1337");
rewritehostport("10.20.30.2:2345");
sl_send_reply("302", "Redirect");
exit;
}
if (uri=~"^proto:[+]*4444.*"){
rewritehostport("10.10.10.2:1337");
rewritehostport("10.20.30.2:2345");
sl_send_reply("302", "Redirect");
exit;
}
if (uri=~"^proto:[+]*3333.*"){
rewritehostport("10.10.10.2:1337");
rewritehostport("10.20.30.2:2345");
sl_send_reply("302", "Redirect");
exit;
}
I am looking for a method to selective ignore a variable (say 55555) along with the lines up until the curly bracket }
awk '/proto/{a=1} a; /{/{a=0}' myfile.cfg ignores the center piece but still yields the beginning portion:
if (uri=~"^proto:[+]*55555.*"){
I'd like to be able to look for certain patterns and ignore those I choose to ignore, e.g., find 5555 and 3333 and ignore that entire string, leaving 4444 alone. I initially thought something to the tune of:
awk '!/4444/ && /proto/{a=1} a; /{/{a=0}'
But its non functional. So I said hrmm perl loops:
if ($_[1] =~ /proto/) {
if ($_[6] =~ /\}/) {
print "something\n";
foreach (#_) {
print $_;
}
print "something\n";
}
}
Buttttttt... that wouldn't always work because some lines might be:
if (uri=~"^proto:[+]*9999.*"){
rewritehostport("10.10.10.2:1337");
sl_send_reply("302", "Redirect");
exit;
}
Then I thought: grep -wvf file_with_data_I_want_removed original_file >> new_file But that defeats the purpose because I'd have to create file_with_data_I_want_removed
In essence, I want to say:
for [ this list of numbers (55555, 3333) ]
go into this_file if_number_exists remove line with number along with everything until the nearest curly bracket while ignoring the other ones
done
if (uri=~"^proto:[+]*4444.*"){
rewritehostport("10.10.10.2:1337");
rewritehostport("10.20.30.2:2345");
sl_send_reply("302", "Redirect");
exit;
}
You were very close. Just rearranging the flag state should get you the desired output.
awk '/proto.*(55555|3333)/{a=0};a;/}/{a=1}' myfile.cfg
if (uri=~"^proto:[+]*4444.*"){
rewritehostport("10.10.10.2:1337");
rewritehostport("10.20.30.2:2345");
sl_send_reply("302", "Redirect");
exit;
}
You disable the flag when your pattern that needs to be skipped is seen.
You print the lines for which your flag is set.
When you see the end of pattern enable the flag.
You could set the record separator, through the RS variable to } :
awk '!/4444/' RS='}' ORS='}' file

simulating tail -f in Perl

As per solution provided in perldoc, I am trying to emulate tail -f but it's not working as expected. The below code could print all lines first time but not the newly lines appended. Could you please elaborate if I am missing any thing here.
#!/usr/bin/perl
open (LOGFILE, "aa") or die "could not open file reason $! \n";
for (;;)
{
seek(LOGFILE,0,1); ### clear OF condition
for ($curpos = tell(LOGFILE); <LOGFILE>; $curpos = tell(LOGFILE))
{
print "$_ \n";
}
sleep 1;
seek(LOGFILE,$curpos,0); ### Setting cursor at the EOF
}
works fine for me. How are you updating "aa" ?
You wont see the data immediately if it is a buffered write to "aa".
can you try the following in a different terminal and check whether you are seeing any update.
while ( 1 )
echo "test" >> aa
end
If you are using perl to update aa, check this section on buffering and how to disable.

Perl: How to "die" with no error message?

I run a simple file test in perl with the code below:
my $f1 = "$pre_file";
unless (-e $1) {
print "\n Pre_check file does not exists! \n";
die;
}
It prints the following output:
Pre_check file does not exists!
Died at ./huawei-postcheck line 81.
However I do not want the last line "Died at ./huawei-postcheck line 81.".
I want to to "die" with no error message.
Is it possible?
See the documentation for die.
If the last element of LIST does not end in a newline, the current
script line number and input line number (if any) are also printed,
and a newline is supplied.
So you can get die to work without printing anything by just using die "\n". But given that you have an error message, I can't see why you don't use that.
unless (-e $f1) {
die "\n Pre_check file does not exist!\n";
}
Of course, the difference is that the message will now go to STDERR rather than STDOUT. But that's probably the right place for it to go.
use exit instead of die.
You could just say
die "\n";
to suppress the message.
You probably want to exit 1 instead of dying then.
my $f1 = "$pre_file";
unless (-e $1) {
print "\n Pre_check file does not exists! \n";
exit 1;
}

remove elements from file using Perl

Input.txt
CASE
REPEAT 1 TIMES
ENDREPEAT
ENDCASE
REPEAT
ENDREPEAT
CASE
REPEAT 2 TIMES
ENDREPEAT
ENDCASE
code.pl
open (FH, "input.txt");
my #arr = <FH>;
foreach (#arr) {
if ($_ =~ s/ENDCASE.*?CASE//gsi) {
$_ = s/ENDCASE.*?CASE//gsi;
}
}
print #arr;
Output : perl code.pl
It prints the Array without modifying........
CASE
REPEAT 1 TIMES
ENDREPEAT
ENDCASE
REPEAT ===> To be Removed
ENDREPEAT ===> To be Removed
CASE
REPEAT 2 TIMES
ENDREPEAT
ENDCASE
Output Needed is, ***||||||||||||****
CASE
REPEAT 1 TIMES
ENDREPEAT
ENDCASE
************Content Removed*****************
CASE
REPEAT 2 TIMES
ENDREPEAT
ENDCASE
Please Guide me to get this output.
Thanks in advance.........
This can be done through the command line as well à la flip-flop operator.
To just output the result to screen
$ perl -ne 'print if /^CASE/ .. /^ENDCASE/' Input.txt
To direct the output to another file
$ perl -ne 'print if /^CASE/ .. /^ENDCASE/' Input.txt > output.txt
To modify the file in-place
$ perl -ni.bak -e 'print if /^CASE/ .. /^ENDCASE/' Input.txt
Replace ' (single-quotes) with "(double-quotes) if on Windows.
You've got a couple of suggestions of ways to address your problem, but you might be interested to hear why your solution didn't work. There are a couple of reasons.
Firstly, When you read your file into #arr you get one line of the file in each element of the array. And when you process the array an element at at time, no element contains both ENDCASE and CASE so your regex never matches and nothing is changed.
For your approach to work, you need to rewrite the program to process the whole file in one go. (I've also cleaned up your code a little.)
#!/usr/bin/perl
use strict;
use warnings;
open (my $fh, '<', 'input.txt') or die $!;
my $file = do { local $/; <$fh> };
$file =~ s/ENDCASE.*?CASE//gsi;
print $file;
But this doesn't fix the problem. It gives the output:
CASE
REPEAT 1 TIMES
ENDREPEAT
REPEAT 2 TIMES
ENDREPEAT
ENDCASE
That's because the ENDCASE and CASE are included in your regex so they get removed. You'll need to look at lookahead and lookbehind assertions in perlre to fix this issue. I'll leave that as an exercise for the reader.
Tie your file using Tie::File:
tie #array, 'Tie::File', filename or die ...;
Manipulate the lines, in any way you see fit, and then untie the array:
untie #array;
Thus, your modifications will be reflected in the original file.
Here's a weird idea that just might work.
use English qw<$INPLACE_EDIT $RS>;
$INPLACE_EDIT = '.bak';
local $RS = "CASE\n";
while ( <$input> ) {
print(( !/^(END)?CASE\n\z/ms or $1 ) ? $_ : $RS );
}
The idea is that you break up your records not by newlines, but by CASE + \n and thus you get to treat all the lines between an ENDCASE and a CASE as one record that you can simply replace with "CASE\n".
Note that we simply print the record unless we see a line start before 'ENDCASE' or 'CASE' followed by a newline. So even though we make a pretty brittle assumption when breaking up the records, we check our assumption before modifying the record. Also if it matches "ENDCASE\n" then $1 is 'END' and we print that record unmodified.
This can break, though. If for some reason you were capable of having a comment here:
ENDCASE
REPEAT ===> This prints because it ends with CASE
ENDREPEAT
CASE
Then the first line would be printed. So we could do this:
my $match = 0;
my $old_1;
while ( <$input> ) {
if ( m/^(END)?CASE\n\z/ms and not $1 ) {
print $RS;
}
else {
next if $old_1;
print;
}
$old_1 = $1;
}

Why can't I match my string from standard input in Perl?

Why will my script not work correctly?
I follow a YouTube video and worked for the guy.
I am running Perl on Windows using ActiveState ActivePerl 5.12.2.1202
Here is my tiny tiny code block.
print "What is your name?\n";
$name = <STDIN>;
if ($name eq "Jon") {
print "We have met before!\n";
} else {
print "We have not met before.\n";
}
The code automatically jumps to the else statement and does not even check the if statement.
The statement $name = <STDIN>; reads from standard input and includes the terminating newline character "\n". Remove this character using the chomp function:
print "What is your name?\n";
$name = <STDIN>;
chomp($name);
if ($name eq "Jon") {
print "We have met before!\n";
} else {
print "We have not met before.\n";
}
The trick in programming is to know what your data are. When something's not acting like you expect, look at the data to see if they are what you expect. For instance:
print "The name is [$name]\n";
You put the braces around it so you can see any extra whitespace that might be there. In this case, you would have seen:
The name is [Jon
]
That's your clue that there is extra stuff. Since the eq has to match exactly, it fails to match.
If you're just starting with Perl, try Learning Perl. It's much better than random videos from YouTube. :)
When you read the name standard input as $name = <STDIN>;
$name will have a trailing newline. So if I enter foo , $name will actually have foo\n.
To get rid of this newline you an make use of the chomp function as:
chomp($name = <STDIN>);